Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Multiple convolution neural networks approach for online handwriting recognition

, 9 Apr 2013
The research focuses on the presentation of word recognition technique for an online handwriting recognition system which uses multiple component neural networks (MCNN) as the exchangeable parts of the classifier.
capital_letter_v2.zip
digit_v2.zip
lower_case_letter_v2.zip
UNIPENviewer_source_code-noexe.zip
UNIPENviewer
DocToolkit
DocToolkit.csproj.user
DocToolkit.snk
obj
Debug
Release
DrawTools
about.bmp
App.ico
bin
Debug
Release
DrawTools.csproj.user
ellipse.bmp
Ellipse.cur
line.bmp
Line.cur
new.bmp
obj
Debug
DrawTools.DrawArea.resources
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
Release
DrawTools.DrawArea.resources
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
open.bmp
pencil.bmp
Pencil.cur
pointer.bmp
PolyHandle.cur
rectangle.bmp
Rectangle.cur
save.bmp
NNControl
bin
Debug
Common
NNTesting
NNTraining
obj
Debug
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
NNControl.Common.UPTemplateControl.resources
NNControl.FlashForm.resources
NNControl.NNTesting.NNTestingControl.resources
NNControl.NNTesting.TextSpellControl.resources
NNControl.NNTraining.ConvolutionForm.resources
NNControl.NNTraining.CreateNetworkForm.resources
NNControl.NNTraining.FullConnectedForm.resources
NNControl.NNTraining.InputLayerForm.resources
NNControl.NNTraining.OutputLayerForm.resources
NNControl.NNTraining.UP_NNTrainingControl.resources
NNControl.Properties.Resources.resources
NNControl.TrainingParametersForm.resources
NNControl.UPViewer.UpImageViewer.resources
UPControl.Common.BaseControl.resources
UPControl.Common.UPTemplateControl.resources
UPControl.FlashForm.resources
UPControl.NNTraining.UP_NNTrainingControl.resources
UPControl.TrainingParametersForm.resources
UPControl.UPViewer.UpImageViewer.resources
UP_NeuralTraining.FlashForm.resources
UP_NeuralTraining.TrainingParametersForm.resources
UP_NeuralTraining.UP_NNTrainingControl.resources
Release
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
NNControl.Common.UPTemplateControl.resources
NNControl.FlashForm.resources
NNControl.NNTesting.NNTestingControl.resources
NNControl.NNTraining.ConvolutionForm.resources
NNControl.NNTraining.CreateNetworkForm.resources
NNControl.NNTraining.FullConnectedForm.resources
NNControl.NNTraining.InputLayerForm.resources
NNControl.NNTraining.OutputLayerForm.resources
NNControl.NNTraining.UP_NNTrainingControl.resources
NNControl.Properties.Resources.resources
NNControl.TrainingParametersForm.resources
NNControl.UPViewer.UpImageViewer.resources
Properties
Resources
btnBack.png
btnDrag.png
btnFitToScreen.png
btnNext.png
btnOpen.png
btnPreview.png
btnRotate270.png
btnRotate90.png
btnSelect.png
btnZoomIn.png
btnZoomOut.png
circle.png
clear.png
color_line.png
cry.png
document-new.png
Drag.cur
draw_line.png
ellipse.png
export.png
file.png
fingerprint-recognition.png
folder-open.png
folder.png
folders_explorer.png
Grab.cur
home.png
label-link.png
pointer.png
rectangle.png
save_accept.png
script_(stop).gif
smile.png
stock_draw-line.png
Stop sign.png
Upload.png
user-group-new.png
UPViewer
Perceptron
ActivationFunction
ArchiveSerialization
bin
Debug
Common
Connections
Layers
Network
Neurons
obj
Debug
ANN.Perceptron.Common.BaseControl.resources
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
Neurons.BaseControl.resources
Release
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
Neurons.BaseControl.resources
Properties
Weights
SpellChecker
bin
Debug
Controls
Dictionary
Affix
Dictionary.bmp
Phonetic
doc
NetSpell.ndoc
Forms
Interactive.bmp
obj
Debug
ResGen.read.1.tlog
ResGen.write.1.tlog
SpellChecker.Dictionary.WordDictionary.resources
SpellChecker.Forms.OptionForm.resources
SpellChecker.MultipleSpelling.resources
SpellChecker.NewSpelling.resources
Spell.snk
Spelling.bmp
UNIPENviewer.suo
UNIPENviewer.v11.suo
UNIPENviewer
bin
Debug
Config
de-DE.dic
en-US.dic
fr-FR.dic
it-IT.dic
UNIPENviewer.vshost.exe.manifest
Release
Config
obj
Debug
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
UNIPENviewer.MainForm.resources
UNIPENviewer.Properties.Resources.resources
Release
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
UNIPENviewer.MainForm.resources
UNIPENviewer.Properties.Resources.resources
x86
Debug
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
UNIPENviewer.Form1.resources
UNIPENviewer.Properties.Resources.resources
Properties
Settings.settings
UPImage
Common
Data
FileFormat
obj
Debug
Release
Properties
UNIPENviewer_source_code.zip
bin
Debug
DocToolkit.dll
Release
DocToolkit.dll
DocToolkit.csproj.user
DocToolkit.snk
DocToolkit.dll
DocToolkit.dll
about.bmp
App.ico
DocToolkit.dll
DrawTools.dll
DocToolkit.dll
DrawTools.dll
DrawTools.csproj.user
ellipse.bmp
Ellipse.cur
line.bmp
Line.cur
new.bmp
DrawTools.dll
DrawTools.DrawArea.resources
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
DrawTools.dll
DrawTools.DrawArea.resources
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
open.bmp
pencil.bmp
Pencil.cur
pointer.bmp
PolyHandle.cur
rectangle.bmp
Rectangle.cur
save.bmp
DocToolkit.dll
DrawTools-LinhLam.dll
DrawTools.dll
NNControl-LinhLam.dll
NNControl.dll
Perceptron.dll
SpellChecker.dll
UP-NeuralTraining.dll
UPImage-LinhLam.dll
UpImage.dll
Release
DocToolkit.dll
DrawTools.dll
Neurons.dll
NNControl.dll
UPImage.dll
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
NNControl-LinhLam.dll
NNControl.Common.UPTemplateControl.resources
NNControl.dll
NNControl.FlashForm.resources
NNControl.NNTesting.NNTestingControl.resources
NNControl.NNTesting.TextSpellControl.resources
NNControl.NNTraining.ConvolutionForm.resources
NNControl.NNTraining.CreateNetworkForm.resources
NNControl.NNTraining.FullConnectedForm.resources
NNControl.NNTraining.InputLayerForm.resources
NNControl.NNTraining.OutputLayerForm.resources
NNControl.NNTraining.UP_NNTrainingControl.resources
NNControl.Properties.Resources.resources
NNControl.TrainingParametersForm.resources
NNControl.UPViewer.UpImageViewer.resources
TempPE
Properties.Resources.Designer.cs.dll
UP-NeuralTraining.dll
UPControl.Common.BaseControl.resources
UPControl.Common.UPTemplateControl.resources
UPControl.FlashForm.resources
UPControl.NNTraining.UP_NNTrainingControl.resources
UPControl.TrainingParametersForm.resources
UPControl.UPViewer.UpImageViewer.resources
UP_NeuralTraining.FlashForm.resources
UP_NeuralTraining.TrainingParametersForm.resources
UP_NeuralTraining.UP_NNTrainingControl.resources
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
NNControl.Common.UPTemplateControl.resources
NNControl.dll
NNControl.FlashForm.resources
NNControl.NNTesting.NNTestingControl.resources
NNControl.NNTraining.ConvolutionForm.resources
NNControl.NNTraining.CreateNetworkForm.resources
NNControl.NNTraining.FullConnectedForm.resources
NNControl.NNTraining.InputLayerForm.resources
NNControl.NNTraining.OutputLayerForm.resources
NNControl.NNTraining.UP_NNTrainingControl.resources
NNControl.Properties.Resources.resources
NNControl.TrainingParametersForm.resources
NNControl.UPViewer.UpImageViewer.resources
TempPE
Properties.Resources.Designer.cs.dll
btnBack.png
btnDrag.png
btnFitToScreen.png
btnNext.png
btnOpen.png
btnPreview.png
btnRotate270.png
btnRotate90.png
btnSelect.png
btnZoomIn.png
btnZoomOut.png
circle.png
clear.png
color_line.png
cry.png
document-new.png
Drag.cur
draw_line.png
ellipse.png
export.png
file.png
fingerprint-recognition.png
folder-open.png
folder.png
folders_explorer.png
Grab.cur
home.png
label-link.png
pointer.png
rectangle.png
save_accept.png
script_(stop).gif
smile.png
stock_draw-line.png
Stop sign.png
Upload.png
user-group-new.png
AForgeLibrary.dll
NeuralNetworkLibrary.dll
Perceptron.dll
SpellChecker.dll
UpImage.dll
Release
NeuralNetworkLibrary.dll
Neurons.dll
UPImage.dll
ANN.Perceptron.Common.BaseControl.resources
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
NeuralNetworkLibrary.dll
Neurons.BaseControl.resources
Perceptron.dll
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
NeuralNetworkLibrary.dll
Neurons.BaseControl.resources
Neurons.dll
SpellChecker.dll
Dictionary.bmp
NetSpell.ndoc
Interactive.bmp
NetSpell.SpellChecker.dll
ResGen.read.1.tlog
ResGen.write.1.tlog
SpellChecker.Dictionary.WordDictionary.resources
SpellChecker.dll
SpellChecker.Forms.OptionForm.resources
SpellChecker.MultipleSpelling.resources
SpellChecker.NewSpelling.resources
Spell.snk
Spelling.bmp
UNIPENviewer.suo
UNIPENviewer.v11.suo
de-DE.dic
DocToolkit.dll
DrawTools-LinhLam.dll
DrawTools.dll
en-US.dic
fr-FR.dic
it-IT.dic
NNControl-LinhLam.dll
NNControl.dll
Perceptron.dll
SpellChecker.dll
UNIPENviewer-LinhLam.exe
UNIPENviewer.exe
UNIPENviewer.vshost.exe
UNIPENviewer.vshost.exe.manifest
UPImage-LinhLam.dll
UpImage.dll
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
TempPE
Properties.Resources.Designer.cs.dll
UNIPENviewer-LinhLam.exe
UNIPENviewer.exe
UNIPENviewer.MainForm.resources
UNIPENviewer.Properties.Resources.resources
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
UNIPENviewer.exe
UNIPENviewer.MainForm.resources
UNIPENviewer.Properties.Resources.resources
GenerateResource.read.1.tlog
GenerateResource.write.1.tlog
UNIPENviewer.exe
UNIPENviewer.Form1.resources
UNIPENviewer.Properties.Resources.resources
Settings.settings
bin
Debug
AForgeLibrary.dll
UPDatabase.dll
UpImage-LinhLam.dll
UpImage.dll
UPUnipenLib.dll
Release
UPImage.dll
UPDatabase.dll
UpImage-LinhLam.dll
UpImage.dll
UPUnipenLib.dll
UPImage.dll
Word_samples.zip
Word samples
beach.dtl
Bengal.dtl
best.dtl
Brower.dtl
Buy.dtl
Byte byte.dtl
Change.dtl
Color.dtl
Company.dtl
Complet.dtl
copy.dtl
cup.dtl
draw tool.dtl
Eastern.dtl
Eat.dtl
eldest.dtl
Emergency.dtl
English.dtl
File.dtl
Finist.dtl
found nothing.dtl
France.dtl
Future.dtl
help me now.dtl
Hey hello.dtl
Hobby.dtl
How are you.dtl
Huck.dtl
icon.dtl
inker.dtl
Internet.dtl
Link.dtl
load.dtl
Local.dtl
Lonely.dtl
loosen.dtl
love you.dtl
Madden.dtl
Main gate.dtl
Mercy.dtl
Module.dtl
monday.dtl
Moon.dtl
mouse.dtl
my turn.dtl
net spell.dtl
network.dtl
never.dtl
newest.dtl
noted.dtl
Novel.dtl
oldest.dtl
Option.dtl
Pencil.dtl
petro.dtl
Pink.dtl
quick and slow.dtl
Rock.dtl
save.dtl
Sell.dtl
slam.dtl
smart phone.dtl
Strong.dtl
Strongest.dtl
success.dtl
Summer.dtl
Take.dtl
Text.dtl
Took.dtl
Train.dtl
Tuesday.dtl
Valence.dtl
Victory.dtl
viewer.dtl
vintage.dtl
Volume.dtl
water.dtl
Weak.dtl
Window.dtl
Windy.dtl
word expert.dtl
// Copyright (c) 2003, Paul Welter
// All rights reserved.

using System;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Forms.Design;
using System.Drawing;
using System.Drawing.Design;
using System.Globalization;
using System.Collections.Generic;
using SpellChecker.Forms;
using SpellChecker.Dictionary;
using SpellChecker.Dictionary.Affix;
using SpellChecker.Dictionary.Phonetic;


namespace SpellChecker
{
	/// <summary>
	///		The Spelling class encapsulates the functions necessary to check
	///		the spelling of inputted text.
	/// </summary>
	[ToolboxBitmap(typeof(SpellChecker.NewSpelling), "Spelling.bmp")]
	public class MultipleSpelling : System.ComponentModel.Component
	{

		#region Global Regex
		// Regex are class scope and compiled to improve performance on reuse
		private Regex _digitRegex = new Regex(@"^\d", RegexOptions.Compiled);
		private Regex _htmlRegex = new Regex(@"</[c-g\d]+>|</[i-o\d]+>|</[a\d]+>|</[q-z\d]+>|<[cg]+[^>]*>|<[i-o]+[^>]*>|<[q-z]+[^>]*>|<[a]+[^>]*>|<(\[^\]*\|'[^']*'|[^'\>])*>", RegexOptions.IgnoreCase & RegexOptions.Compiled);
		private MatchCollection _htmlTags;
		private Regex _letterRegex = new Regex(@"\D", RegexOptions.Compiled);
		private Regex _upperRegex = new Regex(@"[^A-Z]", RegexOptions.Compiled);
		private Regex _wordEx = new Regex(@"\b[A-Za-z0-9_'�-�]+\b", RegexOptions.Compiled);
		private MatchCollection _words;
		#endregion

		#region private variables
		private System.ComponentModel.Container components = null;
		#endregion

		#region Events

		/// <summary>
		///     This event is fired when a word is deleted
		/// </summary>
		/// <remarks>
		///		Use this event to update the parent text
		/// </remarks>
		public event DeletedWordEventHandler DeletedWord;

		/// <summary>
		///     This event is fired when word is detected two times in a row
		/// </summary>
		public event DoubledWordEventHandler DoubledWord;

		/// <summary>
		///     This event is fired when the spell checker reaches the end of
		///     the text in the Text property
		/// </summary>
		public event EndOfTextEventHandler EndOfText;

		/// <summary>
		///     This event is fired when a word is skipped
		/// </summary>
		public event IgnoredWordEventHandler IgnoredWord;

		/// <summary>
		///     This event is fired when the spell checker finds a word that 
		///     is not in the dictionaries
		/// </summary>
		public event MisspelledWordEventHandler MisspelledWord;

		/// <summary>
		///     This event is fired when a word is replace
		/// </summary>
		/// <remarks>
		///		Use this event to update the parent text
		/// </remarks>
		public event ReplacedWordEventHandler ReplacedWord;


		/// <summary>
		///     This represents the delegate method prototype that
		///     event receivers must implement
		/// </summary>
		public delegate void DeletedWordEventHandler(object sender, SpellingEventArgs e);

		/// <summary>
		///     This represents the delegate method prototype that
		///     event receivers must implement
		/// </summary>
		public delegate void DoubledWordEventHandler(object sender, SpellingEventArgs e);

		/// <summary>
		///     This represents the delegate method prototype that
		///     event receivers must implement
		/// </summary>
		public delegate void EndOfTextEventHandler(object sender, System.EventArgs e);

		/// <summary>
		///     This represents the delegate method prototype that
		///     event receivers must implement
		/// </summary>
		public delegate void IgnoredWordEventHandler(object sender, SpellingEventArgs e);

		/// <summary>
		///     This represents the delegate method prototype that
		///     event receivers must implement
		/// </summary>
		public delegate void MisspelledWordEventHandler(object sender, SpellingEventArgs e);

		/// <summary>
		///     This represents the delegate method prototype that
		///     event receivers must implement
		/// </summary>
		public delegate void ReplacedWordEventHandler(object sender, ReplaceWordEventArgs e);

		/// <summary>
		///     This is the method that is responsible for notifying
		///     receivers that the event occurred
		/// </summary>
		protected virtual void OnDeletedWord(SpellingEventArgs e)
		{
			if (DeletedWord != null)
			{
				DeletedWord(this, e);
			}
		}

		/// <summary>
		///     This is the method that is responsible for notifying
		///     receivers that the event occurred
		/// </summary>
		protected virtual void OnDoubledWord(SpellingEventArgs e)
		{
			if (DoubledWord != null)
			{
				DoubledWord(this, e);
			}
		}

		/// <summary>
		///     This is the method that is responsible for notifying
		///     receivers that the event occurred
		/// </summary>
		protected virtual void OnEndOfText(System.EventArgs e)
		{
			if (EndOfText != null)
			{
				EndOfText(this, e);
			}
		}

		/// <summary>
		///     This is the method that is responsible for notifying
		///     receivers that the event occurred
		/// </summary>
		protected virtual void OnIgnoredWord(SpellingEventArgs e)
		{
			if (IgnoredWord != null)
			{
				IgnoredWord(this, e);
			}
		}

		/// <summary>
		///     This is the method that is responsible for notifying
		///     receivers that the event occurred
		/// </summary>
		protected virtual void OnMisspelledWord(SpellingEventArgs e)
		{
			if (MisspelledWord != null)
			{
				MisspelledWord(this, e);
			}
		}

		/// <summary>
		///     This is the method that is responsible for notifying
		///     receivers that the event occurred
		/// </summary>
		protected virtual void OnReplacedWord(ReplaceWordEventArgs e)
		{
			if (ReplacedWord != null)
			{
				ReplacedWord(this, e);
			}
		}

		#endregion

		#region Constructors
		/// <summary>
		///     Initializes a new instance of the SpellCheck class
		/// </summary>
		public MultipleSpelling()
		{
			InitializeComponent();
		}


		/// <summary>
		///     Required for Windows.Forms Class Composition Designer support
		/// </summary>
        public MultipleSpelling(System.ComponentModel.IContainer container)
		{
			container.Add(this);
			InitializeComponent();
		}

		#endregion

		#region private methods

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
					components.Dispose();
				
			}
			base.Dispose( disposing );
		}

		/// <summary>
		///     Calculates the words from the Text property
		/// </summary>
		private void CalculateWords()
		{
			// splits the text into words
			_words = _wordEx.Matches(_text.ToString());
			
			// remark html
			this.MarkHtml();
		}

		/// <summary>
		///     Determines if the string should be spell checked
		/// </summary>
		/// <param name="characters" type="string">
		///     <para>
		///         The Characters to check
		///     </para>
		/// </param>
		/// <returns>
		///     Returns true if the string should be spell checked
		/// </returns>
		private bool CheckString(string characters)
		{
			if(_ignoreAllCapsWords && !_upperRegex.IsMatch(characters))
			{
				return false;
			}
			if(_ignoreWordsWithDigits && _digitRegex.IsMatch(characters))
			{
				return false;
			}
			if(!_letterRegex.IsMatch(characters))
			{
				return false;
			}
			if(_ignoreHtml)
			{
				int startIndex = _words[this.WordIndex].Index;
				
				foreach (Match item in _htmlTags) 
				{
					if (startIndex >= item.Index && startIndex <= item.Index + item.Length - 1)
					{
						return false;
					}
				}
			}
			return true;
		}

		private void Initialize()
		{
            if (_dictionaries == null)
            {
                _dictionaries = new DictionaryCollection();
            }
            else
            {
                foreach (WordDictionary _dictionary in _dictionaries)
                {
                    if (!_dictionary.Initialized)
                        _dictionary.Initialize();
                }
                _isDictionariesInitialized = true;
            }

		}
		/// <summary>
		///     Calculates the position of html tags in the Text property
		/// </summary>
		private void MarkHtml()
		{
			// splits the text into words
			_htmlTags = _htmlRegex.Matches(_text.ToString());
		}

		/// <summary>
		///     Resets the public properties
		/// </summary>
		private void Reset()
		{
			_wordIndex = 0; // reset word index
			_replacementWord = "";
			_suggestions.Clear();
		}

		#endregion

		#region ISpell Near Miss Suggetion methods

		/// <summary>
		///		swap out each char one by one and try all the tryme
		///		chars in its place to see if that makes a good word
		/// </summary>
		private void BadChar(ref ArrayList tempSuggestion)
		{
            foreach (WordDictionary dictionary in Dictionaries)
            {
                for (int i = 0; i < this.CurrentWord.Length; i++)
                {
                    StringBuilder tempWord = new StringBuilder(this.CurrentWord);
                    char[] tryme = dictionary.TryCharacters.ToCharArray();
                    for (int x = 0; x < tryme.Length; x++)
                    {
                        tempWord[i] = tryme[x];
                        if (this.TestWord(tempWord.ToString()))
                        {
                            Word ws = new Word();
                            ws.Text = tempWord.ToString().ToLower();
                            ws.EditDistance = this.EditDistance(this.CurrentWord, tempWord.ToString());

                            tempSuggestion.Add(ws);
                        }
                    }
                }
            }
		}

		/// <summary>
		///     try omitting one char of word at a time
		/// </summary>
		private void ExtraChar(ref ArrayList tempSuggestion)
		{
			if (this.CurrentWord.Length > 1) 
			{
				for (int i = 0; i < this.CurrentWord.Length; i++)
				{
					StringBuilder tempWord = new StringBuilder(this.CurrentWord);
					tempWord.Remove(i, 1);

					if (this.TestWord(tempWord.ToString())) 
					{
						Word ws = new Word();
						ws.Text = tempWord.ToString().ToLower(CultureInfo.CurrentUICulture);
						ws.EditDistance = this.EditDistance(this.CurrentWord, tempWord.ToString());
				
						tempSuggestion.Add(ws);
					}
								 
				}
			}
		}

		/// <summary>
		///     try inserting a tryme character before every letter
		/// </summary>
		private void ForgotChar(ref ArrayList tempSuggestion)
		{
            foreach (WordDictionary dictionary in Dictionaries)
            {

                char[] tryme = dictionary.TryCharacters.ToCharArray();

                for (int i = 0; i <= this.CurrentWord.Length; i++)
                {
                    for (int x = 0; x < tryme.Length; x++)
                    {
                        StringBuilder tempWord = new StringBuilder(this.CurrentWord);

                        tempWord.Insert(i, tryme[x]);
                        if (this.TestWord(tempWord.ToString()))
                        {
                            Word ws = new Word();
                            ws.Text = tempWord.ToString().ToLower();
                            ws.EditDistance = this.EditDistance(this.CurrentWord, tempWord.ToString());

                            tempSuggestion.Add(ws);
                        }
                    }
                }
            }
		}

		/// <summary>
		///     suggestions for a typical fault of spelling, that
		///		differs with more, than 1 letter from the right form.
		/// </summary>
		private void ReplaceChars(ref ArrayList tempSuggestion)
		{
            foreach (WordDictionary dictionary in Dictionaries)
            {
                ArrayList replacementChars = dictionary.ReplaceCharacters;
                for (int i = 0; i < replacementChars.Count; i++)
                {
                    int split = ((string)replacementChars[i]).IndexOf(' ');
                    string key = ((string)replacementChars[i]).Substring(0, split);
                    string replacement = ((string)replacementChars[i]).Substring(split + 1);

                    int pos = this.CurrentWord.IndexOf(key);
                    while (pos > -1)
                    {
                        string tempWord = this.CurrentWord.Substring(0, pos);
                        tempWord += replacement;
                        tempWord += this.CurrentWord.Substring(pos + key.Length);

                        if (this.TestWord(tempWord))
                        {
                            Word ws = new Word();
                            ws.Text = tempWord.ToString().ToLower();
                            ws.EditDistance = this.EditDistance(this.CurrentWord, tempWord.ToString());

                            tempSuggestion.Add(ws);
                        }
                        pos = this.CurrentWord.IndexOf(key, pos + 1);
                    }
                }
            }
		}

		/// <summary>
		///     try swapping adjacent chars one by one
		/// </summary>
		private void SwapChar(ref ArrayList tempSuggestion)
		{
			for (int i = 0; i < this.CurrentWord.Length - 1; i++)
			{
				StringBuilder tempWord = new StringBuilder(this.CurrentWord);
				
				char swap = tempWord[i];
				tempWord[i] = tempWord[i+1];
				tempWord[i+1] = swap;

				if (this.TestWord(tempWord.ToString())) 
				{
					
					Word ws = new Word();
					ws.Text = tempWord.ToString().ToLower();
					ws.EditDistance = this.EditDistance(this.CurrentWord, tempWord.ToString());
				
					tempSuggestion.Add(ws);
				}	 
			}
		}
		
		/// <summary>
		///     split the string into two pieces after every char
		///		if both pieces are good words make them a suggestion
		/// </summary>
		private void TwoWords(ref ArrayList tempSuggestion)
		{
			for (int i = 1; i < this.CurrentWord.Length - 1; i++)
			{
				string firstWord = this.CurrentWord.Substring(0,i);
				string secondWord = this.CurrentWord.Substring(i);
				
				if (this.TestWord(firstWord) && this.TestWord(secondWord)) 
				{
					string tempWord = firstWord + " " + secondWord;
					
					Word ws = new Word();
					ws.Text = tempWord.ToString().ToLower();
					ws.EditDistance = this.EditDistance(this.CurrentWord, tempWord.ToString());
				
					tempSuggestion.Add(ws);
				}	 
			}
		}

        /// <summary>
        ///		swap out each char one by one and try all the tryme
        ///		chars in its place to see if that makes a good word
        /// </summary>
        private bool BadChar(out String result)
        {
            return BadChar(this.CurrentWord, out result);
        }
        /// <summary>
        ///		swap out each char one by one and try all the tryme
        ///		chars in its place to see if that makes a good word
        /// </summary>
        private bool BadChar(String word, out String result)
        {
            result = "";
            bool isFoundWord = false;
            foreach (WordDictionary dictionary in Dictionaries)
            {
                for (int i = 0; i < word.Length; i++)
                {
                    StringBuilder tempWord = new StringBuilder(word);
                    char[] tryme = dictionary.TryCharacters.ToCharArray();
                    for (int x = 0; x < tryme.Length; x++)
                    {
                        tempWord[i] = tryme[x];
                        if (this.TestWord(tempWord.ToString()))
                        {
                            result = tempWord.ToString();
                            isFoundWord = true;
                            return isFoundWord;
                        }
                    }
                }
            }
            return isFoundWord;
        }
        /// <summary>
        ///     try omitting one char of word at a time
        /// </summary>
        private bool ExtraChar(out String result)
        {
            return ExtraChar(this.CurrentWord, out result);

        }
        /// <summary>
        ///     try omitting one char of word at a time
        /// </summary>
        private bool ExtraChar(String word, out String result)
        {
            result = "";
            bool isFoundWord = false;
            if (word.Length > 1)
            {
                for (int i = 0; i < word.Length; i++)
                {
                    StringBuilder tempWord = new StringBuilder(word);
                    tempWord.Remove(i, 1);

                    if (this.TestWord(tempWord.ToString()))
                    {
                        result = tempWord.ToString();
                        isFoundWord = true;
                        break;
                    }

                }
            }
            return isFoundWord;
        }
        /// <summary>
        ///     try inserting a tryme character before every letter
        /// </summary>
        private bool ForgotChar(out String result)
        {
            return ForgotChar(this.CurrentWord, out result);
        }
        /// <summary>
        ///     try inserting a tryme character before every letter
        /// </summary>
        private bool ForgotChar(String word, out String result)
        {
            result = "";
            bool isFoundWord = false;
            foreach (WordDictionary dictionary in Dictionaries)
            {
                char[] tryme = dictionary.TryCharacters.ToCharArray();

                for (int i = 0; i <= word.Length; i++)
                {
                    for (int x = 0; x < tryme.Length; x++)
                    {
                        StringBuilder tempWord = new StringBuilder(word);

                        tempWord.Insert(i, tryme[x]);
                        if (this.TestWord(tempWord.ToString()))
                        {

                            result = tempWord.ToString();
                            isFoundWord = true;
                            return isFoundWord;
                        }
                    }
                }
            }
            return isFoundWord;
        }
        /// <summary>
        ///     suggestions for a typical fault of spelling, that
        ///		differs with more, than 1 letter from the right form.
        /// </summary>
        private bool ReplaceChars(out String result)
        {
            return ReplaceChars(this.CurrentWord, out result);
        }
        /// <summary>
        ///     suggestions for a typical fault of spelling, that
        ///		differs with more, than 1 letter from the right form.
        /// </summary>
        private bool ReplaceChars(String word, out String result)
        {
            result = "";
            bool isFoundWord = false;
            foreach (WordDictionary dictionary in Dictionaries)
            {
                ArrayList replacementChars = dictionary.ReplaceCharacters;
                for (int i = 0; i < replacementChars.Count; i++)
                {
                    int split = ((string)replacementChars[i]).IndexOf(' ');
                    string key = ((string)replacementChars[i]).Substring(0, split);
                    string replacement = ((string)replacementChars[i]).Substring(split + 1);

                    int pos = word.IndexOf(key);
                    while (pos > -1)
                    {
                        string tempWord = word.Substring(0, pos);
                        tempWord += replacement;
                        tempWord += word.Substring(pos + key.Length);

                        if (this.TestWord(tempWord))
                        {

                            result = tempWord.ToString();
                            isFoundWord = true;
                            return isFoundWord;
                        }
                        pos = word.IndexOf(key, pos + 1);
                    }
                }
            }
            return isFoundWord;
        }
        /// <summary>
        ///     try swapping adjacent chars one by one
        /// </summary>
        private bool SwapChar(out String result)
        {
            return SwapChar(this.CurrentWord,out result);
        }
        /// <summary>
        ///     try swapping adjacent chars one by one
        /// </summary>
        private bool SwapChar(String word, out String result)
        {
            result = "";
            bool isFoundWord = false;
            foreach (WordDictionary dictionary in Dictionaries)
            {
                for (int i = 0; i < word.Length - 1; i++)
                {
                    StringBuilder tempWord = new StringBuilder(word);

                    char swap = tempWord[i];
                    tempWord[i] = tempWord[i + 1];
                    tempWord[i + 1] = swap;

                    if (this.TestWord(tempWord.ToString()))
                    {

                        result = tempWord.ToString();
                        isFoundWord = true;
                        return isFoundWord;
                    }
                }
            }
            return isFoundWord;
        }
        /// <summary>
        ///     split the string into two pieces after every char
        ///		if both pieces are good words make them a suggestion
        /// </summary>
        private bool TwoWords(out String result)
        {
            return TwoWords(this.CurrentWord,out result);
        }
        /// <summary>
        ///     split the string into two pieces after every char
        ///		if both pieces are good words make them a suggestion
        /// </summary>
        private bool TwoWords(String word, out String result)
        {
            result = "";
            bool isFoundWord = false;
            for (int i = 1; i < word.Length - 1; i++)
            {
                string firstWord = word.Substring(0, i);
                string secondWord = word.Substring(i);

                if (this.TestWord(firstWord) && this.TestWord(secondWord))
                {
                    string tempWord = firstWord + " " + secondWord;
                    result = tempWord;
                    isFoundWord = true;
                    return isFoundWord;
                }
            }
            return isFoundWord;
        }
		#endregion

		#region public methods

		/// <summary>
		///     Deletes the CurrentWord from the Text Property
		/// </summary>
		/// <remarks>
		///		Note, calling ReplaceWord with the ReplacementWord property set to 
		///		an empty string has the same behavior as DeleteWord.
		/// </remarks>
		public void DeleteWord()
		{
			if (_words == null || _words.Count == 0)
			{
				TraceWriter.TraceWarning("No Words to Delete");
				return;
			}
			string replacedWord = this.CurrentWord;
			int replacedIndex = this.WordIndex;

			int index = _words[replacedIndex].Index;
			int length = _words[replacedIndex].Length;
			
			// adjust length to remove extra white space after first word
			if (index == 0 
				&& index + length < _text.Length 
				&& _text[index+length] == ' ')
			{
				length++; //removing trailing space
			}
			// adjust length to remove double white space
			else if (index > 0 
				&& index + length < _text.Length 
				&& _text[index-1] == ' ' 
				&& _text[index+length] == ' ')
			{					
				length++; //removing trailing space
			}
			// adjust index to remove extra white space before punctuation
			else if (index > 0 
				&& index + length < _text.Length 
				&& _text[index-1] == ' ' 
				&& char.IsPunctuation(_text[index+length]))
			{					
				index--;
				length++;
			}
			// adjust index to remove extra white space before last word
			else if (index > 0 
				&& index + length == _text.Length
				&& _text[index-1] == ' ')	
			{				
				index--;
				length++;
			}

			string deletedWord = _text.ToString(index, length);
			_text.Remove(index, length);
			
			this.CalculateWords();
			this.OnDeletedWord(new SpellingEventArgs(deletedWord, replacedIndex, index));
		}

		/// <summary>
		///     Calculates the minimum number of change, inserts or deletes
		///     required to change firstWord into secondWord
		/// </summary>
		/// <param name="source" type="string">
		///     <para>
		///         The first word to calculate
		///     </para>
		/// </param>
		/// <param name="target" type="string">
		///     <para>
		///         The second word to calculate
		///     </para>
		/// </param>
		/// <param name="positionPriority" type="bool">
		///     <para>
		///         set to true if the first and last char should have priority
		///     </para>
		/// </param>
		/// <returns>
		///     The number of edits to make firstWord equal secondWord
		/// </returns>
		public int EditDistance(string source, string target, bool positionPriority)
		{
		
			// i.e. 2-D array
			Array matrix = Array.CreateInstance(typeof(int), source.Length+1, target.Length+1);

			// boundary conditions
			matrix.SetValue(0, 0, 0); 

			for(int j=1; j <= target.Length; j++)
			{
				// boundary conditions
				int val = (int)matrix.GetValue(0,j-1);
				matrix.SetValue(val+1, 0, j);
			}

			// outer loop
			for(int i=1; i <= source.Length; i++)                            
			{ 
				// boundary conditions
				int val = (int)matrix.GetValue(i-1, 0);
				matrix.SetValue(val+1, i, 0); 

				// inner loop
				for(int j=1; j <= target.Length; j++)                         
				{ 
					int diag = (int)matrix.GetValue(i-1, j-1);

					if(source.Substring(i-1, 1) != target.Substring(j-1, 1)) 
					{
						diag++;
					}

					int deletion = (int)matrix.GetValue(i-1, j);
					int insertion = (int)matrix.GetValue(i, j-1);
					int match = Math.Min(deletion+1, insertion+1);		
					matrix.SetValue(Math.Min(diag, match), i, j);
				}//for j
			}//for i

			int dist = (int)matrix.GetValue(source.Length, target.Length);

			// extra edit on first and last chars
			if (positionPriority)
			{
				if (source[0] != target[0]) dist++;
				if (source[source.Length-1] != target[target.Length-1]) dist++;
			}
			return dist;
		}
		
		/// <summary>
		///     Calculates the minimum number of change, inserts or deletes
		///     required to change firstWord into secondWord
		/// </summary>
		/// <param name="source" type="string">
		///     <para>
		///         The first word to calculate
		///     </para>
		/// </param>
		/// <param name="target" type="string">
		///     <para>
		///         The second word to calculate
		///     </para>
		/// </param>
		/// <returns>
		///     The number of edits to make firstWord equal secondWord
		/// </returns>
		/// <remarks>
		///		This method automatically gives priority to matching the first and last char
		/// </remarks>
		public int EditDistance(string source, string target)
		{
			return this.EditDistance(source, target, true);
		}

		/// <summary>
		///		Gets the word index from the text index.  Use this method to 
		///		find a word based on the text position.
		/// </summary>
		/// <param name="textIndex">
		///		<para>
		///         The index to search for
		///     </para>
		/// </param>
		/// <returns>
		///		The word index that the text index falls on
		/// </returns>
		public int GetWordIndexFromTextIndex(int textIndex)
		{
			if (_words == null || _words.Count == 0 || textIndex < 1)
			{
				TraceWriter.TraceWarning("No words to get text index from.");
				return 0;
			}

			if(_words.Count == 1)
				return 0;

			int low=0; 
			int high=_words.Count-1; 

			// binary search
			while(low<=high) 
			{ 
				int mid=(low+high)/2; 
				int wordStartIndex = _words[mid].Index;
				int wordEndIndex = _words[mid].Index + _words[mid].Length - 1;
			
				// add white space to end of word by finding the start of the next word
				if ((mid+1) < _words.Count)
					wordEndIndex = _words[mid+1].Index - 1;

				if(textIndex < wordStartIndex) 
					high=mid-1; 
				else if(textIndex > wordEndIndex) 
					low=mid+1; 
				else if(wordStartIndex <= textIndex && textIndex <= wordEndIndex) 
					return mid; 
			} 

			// return last word if not found
			return _words.Count-1;
		}

		/// <summary>
		///     Ignores all instances of the CurrentWord in the Text Property
		/// </summary>
		public void IgnoreAllWord()
		{
			if (this.CurrentWord.Length == 0)
			{
				TraceWriter.TraceWarning("No current word");
				return;
			}

			// Add current word to ignore list
			_ignoreList.Add(this.CurrentWord);
			this.IgnoreWord();
		}

		/// <summary>
		///     Ignores the instances of the CurrentWord in the Text Property
		/// </summary>
		/// <remarks>
		///		Must call SpellCheck after call this method to resume
		///		spell checking
		/// </remarks>
		public void IgnoreWord()
		{	
			
			if (_words == null || _words.Count == 0 || this.CurrentWord.Length == 0)
			{
				TraceWriter.TraceWarning("No text or current word");
				return;
			}

			this.OnIgnoredWord(new SpellingEventArgs(
				this.CurrentWord, 
				this.WordIndex, 
				_words[this.WordIndex].Index));

			// increment Word Index to skip over this word
			_wordIndex++;
		}

		/// <summary>
		///     Replaces all instances of the CurrentWord in the Text Property
		/// </summary>
		public void ReplaceAllWord()
		{
			if (this.CurrentWord.Length == 0)
			{
				TraceWriter.TraceWarning("No current word");
				return;
			}

			// if not in list and replacement word has length
			if(!_replaceList.ContainsKey(this.CurrentWord) && _replacementWord.Length > 0) 
			{
				_replaceList.Add(this.CurrentWord, _replacementWord);
			}
			
			this.ReplaceWord();
		}

		/// <summary>
		///     Replaces all instances of the CurrentWord in the Text Property
		/// </summary>
		/// <param name="replacementWord" type="string">
		///     <para>
		///         The word to replace the CurrentWord with
		///     </para>
		/// </param>
		public void ReplaceAllWord(string replacementWord)
		{
			this.ReplacementWord = replacementWord;
			this.ReplaceAllWord();
		}


		/// <summary>
		///     Replaces the instances of the CurrentWord in the Text Property
		/// </summary>
		public void ReplaceWord()
		{
			if (_words == null || _words.Count == 0 || this.CurrentWord.Length == 0)
			{
				TraceWriter.TraceWarning("No text or current word");
				return;
			}

			if (_replacementWord.Length == 0) 
			{
				this.DeleteWord();
				return;
			}
			string replacedWord = this.CurrentWord;
			int replacedIndex = this.WordIndex;

			int index = _words[replacedIndex].Index;
			int length = _words[replacedIndex].Length;
            
			_text.Remove(index, length);
			// if first letter upper case, match case for replacement word
			if (char.IsUpper(_words[replacedIndex].ToString(), 0))
			{
				_replacementWord = _replacementWord.Substring(0,1).ToUpper(CultureInfo.CurrentUICulture) 
					+ _replacementWord.Substring(1);
			}
			_text.Insert(index, _replacementWord);
			
			this.CalculateWords();

			this.OnReplacedWord(new ReplaceWordEventArgs(
				_replacementWord, 
				replacedWord, 
				replacedIndex, 
				index));
		}

		/// <summary>
		///     Replaces the instances of the CurrentWord in the Text Property
		/// </summary>
		/// <param name="replacementWord" type="string">
		///     <para>
		///         The word to replace the CurrentWord with
		///     </para>
		/// </param>
		public void ReplaceWord(string replacementWord)
		{
			this.ReplacementWord = replacementWord;
			this.ReplaceWord();
		}

		/// <summary>
		///     Spell checks the words in the <see cref="Text"/> property starting
		///     at the <see cref="WordIndex"/> position.
		/// </summary>
		/// <returns>
		///     Returns true if there is a word found in the text 
		///     that is not in the dictionaries
		/// </returns>
		/// <seealso cref="CurrentWord"/>
		/// <seealso cref="WordIndex"/>
		public bool SpellCheck()
		{
			return SpellCheck(_wordIndex, this.WordCount-1);
		}

		/// <summary>
		///     Spell checks the words in the <see cref="Text"/> property starting
		///     at the <see cref="WordIndex"/> position. This overload takes in the
		///     WordIndex to start checking from.
		/// </summary>
		/// <param name="startWordIndex" type="int">
		///     <para>
		///         The index of the word to start checking from. 
		///     </para>
		/// </param>
		/// <returns>
		///     Returns true if there is a word found in the text 
		///     that is not in the dictionaries
		/// </returns>
		/// <seealso cref="CurrentWord"/>
		/// <seealso cref="WordIndex"/>
		public bool SpellCheck(int startWordIndex)
		{
			_wordIndex = startWordIndex;
			return SpellCheck();
		}

		/// <summary>
		///     Spell checks a range of words in the <see cref="Text"/> property starting
		///     at the <see cref="WordIndex"/> position and ending at endWordIndex. 
		/// </summary>
		/// <param name="startWordIndex" type="int">
		///     <para>
		///         The index of the word to start checking from. 
		///     </para>
		/// </param>
		/// <param name="endWordIndex" type="int">
		///     <para>
		///         The index of the word to end checking with. 
		///     </para>
		/// </param>
		/// <returns>
		///     Returns true if there is a word found in the text 
		///     that is not in the dictionaries
		/// </returns>
		/// <seealso cref="CurrentWord"/>
		/// <seealso cref="WordIndex"/>
		public bool SpellCheck(int startWordIndex, int endWordIndex)
		{
			if(startWordIndex > endWordIndex || _words == null || _words.Count == 0) 
			{
				// make sure end index is not greater then word count
				this.OnEndOfText(System.EventArgs.Empty);	//raise event
				return false;
			}

			this.Initialize();

			string currentWord = "";
			bool misspelledWord = false;

			for (int i = startWordIndex; i <= endWordIndex; i++) 
			{
				_wordIndex = i;		// saving the current word index 
				currentWord = this.CurrentWord;

				if(CheckString(currentWord)) 
				{
					if(!TestWord(currentWord)) 
					{
						if(_replaceList.ContainsKey(currentWord)) 
						{
							this.ReplacementWord = _replaceList[currentWord].ToString();
							this.ReplaceWord();
						}
						else if(!_ignoreList.Contains(currentWord))
						{
							misspelledWord = true;
							this.OnMisspelledWord(new SpellingEventArgs(currentWord, i, _words[i].Index));		//raise event
							break;
						}
					}
					else if(i > 0 && _words[i-1].Value.ToString() == currentWord 
						&& (_words[i-1].Index + _words[i-1].Length + 1) == _words[i].Index)
					{
						misspelledWord = true;
						this.OnDoubledWord(new SpellingEventArgs(currentWord, i, _words[i].Index));		//raise event
						break;
					}
				}
			} // for

			if(_wordIndex >= _words.Count-1 && !misspelledWord) 
			{
				this.OnEndOfText(System.EventArgs.Empty);	//raise event
			}
		
			return misspelledWord;

		} // SpellCheck
		
		/// <summary>
		///     Spell checks the words in the <see cref="Text"/> property starting
		///     at the <see cref="WordIndex"/> position. This overload takes in the 
		///     text to spell check
		/// </summary>
		/// <param name="text" type="string">
		///     <para>
		///         The text to spell check
		///     </para>
		/// </param>
		/// <returns>
		///     Returns true if there is a word found in the text 
		///     that is not in the dictionaries
		/// </returns>
		/// <seealso cref="CurrentWord"/>
		/// <seealso cref="WordIndex"/>
		public bool SpellCheck(string text)
		{
			this.Text = text;
			return SpellCheck();
		}

		/// <summary>
		///     Spell checks the words in the <see cref="Text"/> property starting
		///     at the <see cref="WordIndex"/> position. This overload takes in 
		///     the text to check and the WordIndex to start checking from.
		/// </summary>
		/// <param name="text" type="string">
		///     <para>
		///         The text to spell check
		///     </para>
		/// </param>
		/// <param name="startWordIndex" type="int">
		///     <para>
		///         The index of the word to start checking from
		///     </para>
		/// </param>
		/// <returns>
		///     Returns true if there is a word found in the text 
		///     that is not in the dictionaries
		/// </returns>
		/// <seealso cref="CurrentWord"/>
		/// <seealso cref="WordIndex"/>
		public bool SpellCheck(string text, int startWordIndex)
		{
			this.WordIndex = startWordIndex;
			this.Text = text;
			return SpellCheck();
		}

		/// <summary>
		///     Populates the <see cref="Suggestions"/> property with word suggestions
		///     for the word
		/// </summary>
		/// <param name="word" type="string">
		///     <para>
		///         The word to generate suggestions on
		///     </para>
		/// </param>
		/// <remarks>
		///		This method sets the <see cref="Text"/> property to the word. 
		///		Then calls <see cref="TestWord"/> on the word to generate the need
		///		information for suggestions. Note that the Text, CurrentWord and WordIndex 
		///		properties are set when calling this method.
		/// </remarks>
		/// <seealso cref="CurrentWord"/>
		/// <seealso cref="Suggestions"/>
		/// <seealso cref="TestWord"/>
		public void Suggest(string word)
		{
			this.Text = word;
			if(!this.TestWord(word))
				this.Suggest();
		}
		/// <summary>
		///     Populates the <see cref="Suggestions"/> property with word suggestions
		///     for the <see cref="CurrentWord"/>
		/// </summary>
		/// <remarks>
		///		<see cref="TestWord"/> must have been called before calling this method
		/// </remarks>
		/// <seealso cref="CurrentWord"/>
		/// <seealso cref="Suggestions"/>
		/// <seealso cref="TestWord"/>
		public void Suggest()
		{
			
			
			// can't generate suggestions with out current word
			if (this.CurrentWord.Length == 0)
			{
				TraceWriter.TraceWarning("No current word");
				return;
			}

			this.Initialize();

			ArrayList tempSuggestion = new ArrayList();
            foreach(WordDictionary _dictionary in _dictionaries)
            {
			    if ((_suggestionMode == SuggestionEnum.PhoneticNearMiss 
				    || _suggestionMode == SuggestionEnum.Phonetic)
				    && _dictionary.PhoneticRules.Count > 0)
			    {
				    // generate phonetic code for possible root word
				    Hashtable codes = new Hashtable();
				    foreach (string tempWord in _dictionary.PossibleBaseWords)
				    {
					    string tempCode = _dictionary.PhoneticCode(tempWord);
					    if (tempCode.Length > 0 && !codes.ContainsKey(tempCode)) 
					    {
						    codes.Add(tempCode, tempCode);
					    }
				    }
				
				    if (codes.Count > 0)
				    {
					    // search root words for phonetic codes
					    foreach (Word word in _dictionary.BaseWords.Values)
					    {
						    if (codes.ContainsKey(word.PhoneticCode))
						    {
							    ArrayList words = _dictionary.ExpandWord(word);
							    // add expanded words
							    foreach (string expandedWord in words)
							    {
								    Word newWord = new Word();
								    newWord.Text = expandedWord;
								    newWord.EditDistance = this.EditDistance(this.CurrentWord, expandedWord);
								    tempSuggestion.Add(newWord);
							    }
						    }
					    }
				    }
				    TraceWriter.TraceVerbose("Suggestiongs Found with Phonetic Stratagy: {0}" , tempSuggestion.Count);
			    }
            }
			if (_suggestionMode == SuggestionEnum.PhoneticNearMiss 
				|| _suggestionMode == SuggestionEnum.NearMiss)
			{
				// suggestions for a typical fault of spelling, that
				// differs with more, than 1 letter from the right form.
				this.ReplaceChars(ref tempSuggestion);

				// swap out each char one by one and try all the tryme
				// chars in its place to see if that makes a good word
				this.BadChar(ref tempSuggestion);

				// try omitting one char of word at a time
				this.ExtraChar(ref tempSuggestion);

				// try inserting a tryme character before every letter
				this.ForgotChar(ref tempSuggestion);

				// split the string into two pieces after every char
				// if both pieces are good words make them a suggestion
				this.TwoWords(ref tempSuggestion);

				// try swapping adjacent chars one by one
				this.SwapChar(ref tempSuggestion);
			}

			TraceWriter.TraceVerbose("Total Suggestiongs Found: {0}" , tempSuggestion.Count);

			tempSuggestion.Sort();  // sorts by edit score
			_suggestions.Clear(); 

			for (int i = 0; i < tempSuggestion.Count; i++)
			{
				string word = ((Word)tempSuggestion[i]).Text;
				// looking for duplicates
				if (!_suggestions.Contains(word))
				{
					// populating the suggestion list
					_suggestions.Add(word);
				}

				if (_suggestions.Count >= _maxSuggestions && _maxSuggestions > 0)
				{
					break;
				}
			}

		} // suggest

		/// <summary>
		///     Checks to see if the word is in the dictionary
		/// </summary>
		/// <param name="word" type="string">
		///     <para>
		///         The word to check
		///     </para>
		/// </param>
		/// <returns>
		///     Returns true if word is found in dictionary
		/// </returns>
		public bool TestWord(string word)
		{
            if (!_isDictionariesInitialized)
            {
                this.Initialize();
            }

			TraceWriter.TraceVerbose("Testing Word: {0}" , word);
            foreach (WordDictionary dictionary in Dictionaries)
            {
                if (dictionary.Contains(word))
                {
                    return true;
                }
                else if (dictionary.Contains(word.ToLower()))
                {
                    return true;
                }
            }
			return false;
		}
        public bool IsSimilarSpellCheck(string word)
        {
            bool bResult = false;
            if (_isDictionariesInitialized == false)
            {
                this.Initialize();
            }
    
            String result;
            // check similar word
            if (this.ReplaceChars(word,out result))
            {
                bResult = true;
            }
            else if (this.BadChar(word, out result))
            {
                bResult = true;
            }
            else if (this.ForgotChar(word, out result))
            {
                bResult = true;
            }
            else if (this.SwapChar(word, out result))
            {
                bResult = true;
            }
            else if (this.ExtraChar(word, out result))
            {
                bResult = true;
            }
            else if (this.TwoWords(word, out result))
            {
                bResult = true;
            }
                
            
            return bResult;

        }
		#endregion

		#region public properties

		private bool _alertComplete = true;
        private DictionaryCollection _dictionaries;
		private bool _ignoreAllCapsWords = true;
		private bool _ignoreHtml = true;
		private ArrayList _ignoreList = new ArrayList();
		private bool _ignoreWordsWithDigits = false;
		private int _maxSuggestions = 25;
		private Hashtable _replaceList = new Hashtable();
		private string _replacementWord = "";
		private SuggestionEnum _suggestionMode = SuggestionEnum.PhoneticNearMiss;
		private ArrayList _suggestions = new ArrayList();
		private StringBuilder _text = new StringBuilder();
		private int _wordIndex = 0;
        private bool _isDictionariesInitialized=false;

		/// <summary>
		///     The suggestion strategy to use when generating suggestions
		/// </summary>
		public enum SuggestionEnum
		{
			/// <summary>
			///     Combines the phonetic and near miss strategies
			/// </summary>
			PhoneticNearMiss,
			/// <summary>
			///     The phonetic strategy generates suggestions by word sound
			/// </summary>
			/// <remarks>
			///		This technique was developed by the open source project ASpell.net
			/// </remarks>
			Phonetic,
			/// <summary>
			///     The near miss strategy generates suggestion by replacing, 
			///     removing, adding chars to make words
			/// </summary>
			/// <remarks>
			///     This technique was developed by the open source spell checker ISpell
			/// </remarks>
			NearMiss
		}


		/// <summary>
		///     Display the 'Spell Check Complete' alert.
		/// </summary>
		[Browsable(true)]
		[DefaultValue(true)]
		[CategoryAttribute("Options")]
		[Description("Display the 'Spell Check Complete' alert.")]
		public bool AlertComplete
		{
			get { return _alertComplete; }
			set { _alertComplete = value; }
		}

		/// <summary>
		///     The current word being spell checked from the text property
		/// </summary>
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public string CurrentWord
		{
			get	
			{
				if(_words == null || _words.Count == 0)
					return string.Empty;
				else
					return _words[this.WordIndex].Value;
			}
		}

		/// <summary>
		///     The WordDictionary object to use when spell checking
		/// </summary>
		[Browsable(true)]
        [CategoryAttribute("Dictionary")]
		[Description("The WordDictionary object to use when spell checking")]
        public DictionaryCollection Dictionaries
		{
			get 
			{
				if(!base.DesignMode && _dictionaries == null)
                    _dictionaries = new DictionaryCollection();

				return _dictionaries;
			}
			set 
			{
                if (value != null)
                {
                    _dictionaries = value;
                }
                else
                { 
                    _dictionaries=new DictionaryCollection();
                }
			}
		}


		/// <summary>
		///     Ignore words with all capital letters when spell checking
		/// </summary>
		[DefaultValue(true)]
		[CategoryAttribute("Options")]
		[Description("Ignore words with all capital letters when spell checking")]
		public bool IgnoreAllCapsWords
		{
			get {return _ignoreAllCapsWords;}
			set {_ignoreAllCapsWords = value;}
		}

		/// <summary>
		///     Ignore html tags when spell checking
		/// </summary>
		[DefaultValue(true)]
		[CategoryAttribute("Options")]
		[Description("Ignore html tags when spell checking")]
		public bool IgnoreHtml
		{
			get {return _ignoreHtml;}
			set {_ignoreHtml = value;}
		}

		/// <summary>
		///     List of words to automatically ignore
		/// </summary>
		/// <remarks>
		///		When <see cref="IgnoreAllWord"/> is clicked, the <see cref="CurrentWord"/> is added to this list
		/// </remarks>
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public ArrayList IgnoreList
		{
			get {return _ignoreList;}
		}

		/// <summary>
		///     Ignore words with digits when spell checking
		/// </summary>
		[DefaultValue(false)]
		[CategoryAttribute("Options")]
		[Description("Ignore words with digits when spell checking")]
		public bool IgnoreWordsWithDigits
		{
			get {return _ignoreWordsWithDigits;}
			set {_ignoreWordsWithDigits = value;}
		}

		/// <summary>
		///     The maximum number of suggestions to generate
		/// </summary>
		[DefaultValue(25)]
		[CategoryAttribute("Options")]
		[Description("The maximum number of suggestions to generate")]
		public int MaxSuggestions
		{
			get {return _maxSuggestions;}
			set {_maxSuggestions = value;}
		}

		/// <summary>
		///     List of words and replacement values to automatically replace
		/// </summary>
		/// <remarks>
		///		When <see cref="ReplaceAllWord"/> is clicked, the <see cref="CurrentWord"/> is added to this list
		/// </remarks>
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public Hashtable ReplaceList
		{
			get {return _replaceList;}
		}

		/// <summary>
		///     The word to used when replacing the misspelled word
		/// </summary>
		/// <seealso cref="ReplaceAllWord"/>
		/// <seealso cref="ReplaceWord"/>
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public string ReplacementWord
		{
			get {return _replacementWord;}
			set {_replacementWord = value.Trim();}
		}
		/// <summary>
		///     The suggestion strategy to use when generating suggestions
		/// </summary>
		[DefaultValue(SuggestionEnum.PhoneticNearMiss)]
		[CategoryAttribute("Options")]
		[Description("The suggestion strategy to use when generating suggestions")]
		public SuggestionEnum SuggestionMode
		{
			get {return _suggestionMode;}
			set {_suggestionMode = value;}
		}

		/// <summary>
		///     An array of word suggestions for the correct spelling of the misspelled word
		/// </summary>
		/// <seealso cref="Suggest"/>
		/// <seealso cref="SpellCheck"/>
		/// <seealso cref="MaxSuggestions"/>
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public ArrayList Suggestions
		{
			get {return _suggestions;}
		}

		/// <summary>
		///     The text to spell check
		/// </summary>
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public string Text
		{
			get {return _text.ToString();}
			set 
			{
				_text = new StringBuilder(value);
				this.CalculateWords();
				this.Reset();
			}
		}

		/// <summary>
		///     TextIndex is the index of the current text being spell checked
		/// </summary>
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public int TextIndex
		{
			get 
			{
				if (_words == null || _words.Count == 0)
					return 0;
	
				return _words[this.WordIndex].Index;			
			}
		}

		/// <summary>
		///     The number of words being spell checked
		/// </summary>
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public int WordCount
		{
			get 
			{
				if(_words == null)
					return 0;

				return _words.Count;
			}
		}

		/// <summary>
		///     WordIndex is the index of the current word being spell checked
		/// </summary>
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public int WordIndex
		{
			get 
			{
				if(_words == null)
					return 0;
				
				// make sure word index can't be higher then word count
				return Math.Max(0, Math.Min(_wordIndex, (this.WordCount-1)));	
			}
			set 
			{	
				_wordIndex = value;	
			}
		}

		#endregion

		#region Component Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			components = new System.ComponentModel.Container();
           _dictionaries = new DictionaryCollection();
		}

		#endregion

	} 
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Vietdungiitb
Vietnam Maritime University
Vietnam Vietnam
No Biography provided

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 10 Apr 2013
Article Copyright 2013 by Vietdungiitb
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid