using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Babebi4
{
	public partial class MainForm : Form
	{
		public MainForm()
		{
			InitializeComponent();
		}

		private string currentXmlFilesDirectoryFullName;

		public BabebiDataSet DataSet
		{
			get
			{
				return this.babebiDataSet;
			}
		}

		#region		Constants

		public const string ModeCode_Letter = "L";
		public const string ModeCode_Symbol = "S";

		public const string ModeName_Letter = "Letter";
		public const string ModeName_Symbol = "Symbol";

		public const string SubscriberCode_Pattern = "P";
		public const string SubscriberCode_Word = "W";

		public const string SubscriberName_None = "(none)";

		public const string SubscriberName_Pattern = "Pattern";
		public const string SubscriberName_Word = "Word";

		public const string ModeName_NotDefined = "(not defined)";
		public const string ModeName_ExNihilo = "Ex nihilo";
		public const string ModeName_FromPattern = "From Pattern";
		public const string ModeName_ByInsertion = "By insertion";
		public const string ModeName_Derivated = "Derivated";
		public const string ModeName_Concatenated = "Concatenated";

		public const string ModeCode_NotDefined = "";
		public const string ModeCode_ExNihilo = "X";
		public const string ModeCode_ByInsertion = "I";
		public const string ModeCode_FromPattern = "P";
		public const string ModeCode_Derivated = "D";
		public const string ModeCode_Concatenated = "C";

		public const string TypeCode_Vowel = "V";
		public const string TypeCode_Consonant = "C";

		public const short	WordTypeId__ProperNoun = 9;	

		#endregion	Constants

		#region		the Current__* rows

		public BabebiDataSet.LanguageRow Current__Language = null;
		public BabebiDataSet.LetterOrSymbol_LanguageRow Current__LetterOrSymbol_Language = null;

		public BabebiDataSet.WordTypeRow Current__WordType = null;
		public BabebiDataSet.WordType_LanguageRow Current__WordType_Language = null;
		public BabebiDataSet.DerivatingWordTypeRow Current__DerivatingWordType = null;
		public BabebiDataSet.DerivatingWordType_LanguageRow Current__DerivatingWordType_Language = null;
		public BabebiDataSet.DerivatedWordTypeRow Current__DerivatedWordType = null;
		public BabebiDataSet.DerivatedWordType_LanguageRow Current__DerivatedWordType_Language = null;
		public BabebiDataSet.DerivatingWordType_DerivatedWordTypeRow Current__DerivatingWordType_DerivatedWordType = null;
		public BabebiDataSet.DerivatingRow Current__Derivating = null;
		public BabebiDataSet.Derivating_LanguageRow Current__Derivating_Language = null;

		public BabebiDataSet.WordOrPatternRow Current__WordOrPattern__of__Pattern = null;
		public BabebiDataSet.PatternRow Current__Pattern = null;
		public BabebiDataSet.Pattern_LanguageRow Current__Pattern_Language = null;

		public BabebiDataSet.PatternByInsertionRow Current__PatternByInsertion = null;
		public BabebiDataSet.WordOrPatternRow Current__WordOrPattern__of__PatternByInsertion__Parent = null;
		public BabebiDataSet.PatternRow Current__Pattern__of__PatternByInsertion__Parent = null;
		public BabebiDataSet.Pattern_LanguageRow Current__Pattern_Language__of__PatternByInsertion__Parent = null;
		public BabebiDataSet.WordRow Current__Word__of__PatternByInsertion__Parent = null;
		public BabebiDataSet.Word_LanguageRow Current__Word_Language__of__PatternByInsertion__Parent = null;

		public BabebiDataSet.PatternFromPatternRow Current__PatternFromPattern = null;
		public BabebiDataSet.FromPatternRow Current__FromPattern__of__PatternFromPattern = null;
		public BabebiDataSet.PatternRow Current__Pattern__of__PatternFromPattern__Parent = null;
		public BabebiDataSet.Pattern_LanguageRow Current__Pattern_Language__of__PatternFromPattern__Parent = null;

		public BabebiDataSet.WordOrPatternRow Current__WordOrPattern__of__Word = null;
		public BabebiDataSet.WordRow Current__Word = null;
		public BabebiDataSet.Word_LanguageRow Current__Word_Language = null;
		public BabebiDataSet.Word_LanguageWordRow Current__Word_LanguageWord__of__Word = null;
		public BabebiDataSet.LanguageWordRow Current__LanguageWord = null;
		public BabebiDataSet.Word_LanguageWordRow Current__Word_LanguageWord__of__LanguageWord = null;

		public BabebiDataSet.WordFromPatternRow		Current__WordFromPattern = null;
		public BabebiDataSet.FromPatternRow			Current__FromPattern__of__WordFromPattern = null;
		public BabebiDataSet.PatternRow				Current__Pattern__of__WordFromPattern__Parent = null;
		public BabebiDataSet.Pattern_LanguageRow	Current__Pattern_Language__of__WordFromPattern__Parent = null;

		/// utilisés dans l'extension WordDerivated (en haut à droite)
		public BabebiDataSet.WordByInsertionRow Current__WordByInsertion = null;
		public BabebiDataSet.WordRow Current__Word__of__WordByInsertion__Parent = null;
		public BabebiDataSet.Word_LanguageRow Current__Word_Language__of__WordByInsertion__Parent = null;
		public BabebiDataSet.LetterClusterRow Current__LetterCluster__of__WordByInsertion = null;

		/// utilisés dans l'extension WordDerivated (en haut à droite)
		public BabebiDataSet.WordDerivatingRow Current__WordDerivating__of__WordDerivated = null;
		public BabebiDataSet.WordRow Current__Word__of__WordDerivating__of__WordDerivated = null;
		public BabebiDataSet.Word_LanguageRow Current__Word_Language__of__WordDerivating__of__WordDerivated = null;
		public BabebiDataSet.WordDerivatedRow Current__WordDerivated = null;
		public BabebiDataSet.DerivatedWordType_LanguageRow Current__DerivatedWordType_Language__of__WordDerivated = null;
		public BabebiDataSet.Derivating_LanguageRow Current__Derivating_Language__of__WordDerivated = null;

		public BabebiDataSet.WordConcatenatedRow Current__WordConcatenated = null;
		public BabebiDataSet.WordConcatenatedComponentRow Current__WordConcatenatedComponent = null;
		public BabebiDataSet.WordRow Current__Word__of__WordConcatenatedComponent = null;
		public BabebiDataSet.Word_LanguageRow Current__Word_Language__of__WordConcatenatedComponent = null;

		///	utilisé pour afficher les (Concatenated) Words qui utilisent ce Word.
		public BabebiDataSet.WordConcatenatedComponentRow Current__WordConcatenating = null;


		#endregion	the Current__* rows

		#region		GuiTables

		#region		GuiTable__DerivatingWordType_DerivatedWordType

		private GuiTable__DerivatingWordType_DerivatedWordType guiTable__DerivatingWordType_DerivatedWordType;
		public BindingSource BindingSource__DerivatingWordType_DerivatedWordType;

		#endregion	GuiTable__DerivatingWordType_DerivatedWordType
		#region		GuiTable__WordByInsertion__of__Current__Word

		private GuiTable__WordByInsertion__of__Current__Word guiTable__WordByInsertion__of__Current__Word;
		public	BindingSource BindingSource__WordByInsertion__of__Current__Word;

		#endregion	GuiTable__WordByInsertion__of__Current__Word
		#region		GuiTable__PatternByInsertion__of__Current__Word

		private GuiTable__PatternByInsertion__of__Current__Word  guiTable__PatternByInsertion__of__Current__Word;
		public	BindingSource								BindingSource__PatternByInsertion__of__Current__Word;

		#endregion	GuiTable__PatternByInsertion__of__Current__Word
		#region		GuiTable__PatternByInsertion__of__Current__Pattern

		private GuiTable__PatternByInsertion__of__Current__Pattern  guiTable__PatternByInsertion__of__Current__Pattern;
		public	BindingSource								   BindingSource__PatternByInsertion__of__Current__Pattern;

		#endregion	GuiTable__PatternByInsertion__of__Current__Pattern
		#region		GuiTable__WordDerivated__of__WordDerivating

	///	private GuiTable__WordDerivated__of__WordDerivating guiTable__WordDerivated__of__WordDerivating;
		private GuiTable__WordDerivated__of__WordDerivating guiTable__WordDerivated__of__WordDerivating;
		public BindingSource BindingSource__WordDerivated__of__WordDerivating;

		#endregion	GuiTable__WordDerivated__of__WordDerivating
		#region		GuiTable__WordFromPattern__of__Current__Pattern

		internal	GuiTable__WordFromPattern__of__Current__Pattern guiTable__WordFromPattern__of__Current__Pattern;
		public		BindingSource BindingSource__WordFromPattern__of__Current__Pattern;

		#endregion	GuiTable__WordFromPattern__of__Current__Pattern
		#region		GuiTable__PatternFromPattern__of__Current__Pattern

		private		GuiTable__PatternFromPattern__of__Current__Pattern guiTable__PatternFromPattern__of__Current__Pattern;
		internal	BindingSource BindingSource__PatternFromPattern__of__Current__Pattern;

		#endregion	GuiTable__PatternFromPattern__of__Current__Pattern
		#region		GuiTable__WordConcatenatedComponent

		internal GuiTable__WordConcatenatedComponent guiTable__WordConcatenatedComponent;
		public BindingSource BindingSource__WordConcatenatedComponent;

		#endregion	GuiTable__WordDerivated__of__WordDerivating
		#region		GuiTable__WordConcatenating

		private GuiTable__WordConcatenating guiTable__WordConcatenating;
		public BindingSource BindingSource__WordConcatenating;

		#endregion	GuiTable__WordConcatenating
		#region		GuiTable__BookSentence

		private GuiTable__BookSentence	     guiTable__BookSentence;
		private BindingSource			bindingSource__BookSentence;

		#endregion	GuiTable__BookSentence
		#region		GuiTable__SentenceWord

		private GuiTable__SentenceWord	     guiTable__SentenceWord;
		private BindingSource			bindingSource__SentenceWord;

		#endregion	GuiTable__SentenceWord
		
		#endregion	GuiTables

		#region		about Vowels and Consonants

		/// l'ordre de ces arrays est celui qui correspond à l'ordre natif des enregistrements des rows dans la DB.
		/// En d'autres termes, on y a créé un ordre alphabetique spécifique au babebi.
		/// Au 2020-12-25, il s'agissait de :
		/// 
		/// x, a, e, i, o, u, q, aa, ee, oo, b, p, c, j, d, t, f, v, g, k, m, n, s, z, l, r, y, w, nn, ( ?, ! )
		/// 
		internal BabebiDataSet.LetterRow[] Vowels;
		internal BabebiDataSet.LetterRow[] Consonants;

		internal string[] VowelStrings;
		internal string[] ConsonantStrings;

		internal BabebiDataSet.LetterRow FirstVowel;
		internal BabebiDataSet.LetterRow FirstConsonant;

		internal BabebiDataSet.SymbolRow TheSymbolForVowel;
		internal BabebiDataSet.SymbolRow TheSymbolForConsonant;

		internal char TheSymbolCharForVowel;
		internal char TheSymbolCharForConsonant;

		#endregion	about Vowels and Consonants

		public bool DoNotTriggerCurrentChangedEvent = false;

		internal List<string> SubStrings__registered_as_being_not_LanguageWords_forever;

		#region		MainForm Load & Close + KeyDown

		private void MainForm_Load(object sender, EventArgs e)
		{
			#region		load the dataSet with the xml file content.

			System.IO.DirectoryInfo directoryInfo = new System.IO.DirectoryInfo("..\\..\\Xmls");

			if (!directoryInfo.Exists)
			{
				throw new ApplicationException("Unable to find the 'Xmls' directory associated to the path: '" + directoryInfo.FullName + "'.");
			}

			this.currentXmlFilesDirectoryFullName = directoryInfo.FullName;

			System.IO.FileInfo[] fileInfos = directoryInfo.GetFiles("BabebiDataSet*.xml");

			if (fileInfos.Length == 0)
			{
				throw new ApplicationException("The 'Xmls' directory (" + directoryInfo.FullName + ") does not contain any file.");
			}

			List<string> fileNames = new List<string>();
			foreach (System.IO.FileInfo fileInfo in fileInfos)
			{
				fileNames.Add(fileInfo.FullName);
			}
			fileNames.Sort();

			string lastXmlFileFullName = fileNames.Last();

			this.DoNotTriggerCurrentChangedEvent = true;
			this.DataSet.ReadXml(lastXmlFileFullName);		/// #################################################################################
			this.DataSet.AcceptChanges();
			this.DoNotTriggerCurrentChangedEvent = false;

			#region		(test si Error lors du chargement...)

			/// <WordDerivating Id="311" WordTypeId="1" DerivatingWordTypeId="1" />			
			/// this.DataSet.WordDerivating.AddWordDerivatingRow(311, 1, 1);

			/// <WordDerivated Id="312" ModeCode="D" WordTypeId="1" DerivatedWordTypeId="1" WordDerivatingId="311" DerivatingWordTypeId="1" DerivatingId="5" />
			/// this.DataSet.WordDerivated.AddWordDerivatedRow(312, "D", 1, 1, 311, 1, 5);

			#endregion	(test si Error lors du chargement...)

			#endregion	load the dataSet with the xml file content.
			#region		useful rows

			#region		Vowels

			BabebiDataSet.LetterRow[] letterRows_Vowel = (BabebiDataSet.LetterRow[])(this.DataSet.Letter.Select("TypeCode = '" + TypeCode_Vowel + "'"));

			SortedDictionary<short, BabebiDataSet.LetterRow> ranks__vowelRows = new SortedDictionary<short, BabebiDataSet.LetterRow>();

			foreach (BabebiDataSet.LetterRow vowelRow in letterRows_Vowel)
			{
				ranks__vowelRows.Add(vowelRow.Rank, vowelRow);
			}

			this.Vowels			= ranks__vowelRows.Values.ToArray();
			this.VowelStrings	= this.Vowels.Select(vowel => vowel.String).ToArray();

			this.FirstVowel = this.Vowels[0];

			#endregion	Vowels
			#region		Consonants

			BabebiDataSet.LetterRow[] letterRows_Consonant = (BabebiDataSet.LetterRow[])(this.DataSet.Letter.Select("TypeCode = '" + TypeCode_Consonant + "'"));

			SortedDictionary<short, BabebiDataSet.LetterRow> ranks__consonantRows = new SortedDictionary<short, BabebiDataSet.LetterRow>();

			foreach (BabebiDataSet.LetterRow consonantRow in letterRows_Consonant)
			{
				ranks__consonantRows.Add(consonantRow.Rank, consonantRow);
			}

			this.Consonants			= ranks__consonantRows.Values.ToArray();
			this.ConsonantStrings	= this.Consonants.Select(consonant => consonant.String).ToArray();

			this.FirstConsonant = this.Consonants[0];

			#endregion	Consonants


			this.TheSymbolForVowel		= (BabebiDataSet.SymbolRow)(this.DataSet.Symbol.Select("TypeCode = '" + TypeCode_Vowel + "'").First());
			this.TheSymbolForConsonant	= (BabebiDataSet.SymbolRow)(this.DataSet.Symbol.Select("TypeCode = '" + TypeCode_Consonant + "'").First());

			this.TheSymbolCharForVowel		= this.TheSymbolForVowel.String[0];
			this.TheSymbolCharForConsonant	= this.TheSymbolForConsonant.String[0];

			#endregion	useful rows
			#region		focus the lastly-used TabPage.

			switch (Properties.Settings.Default.FocusedTabPage)
			{
				case "Language": { this.tabControl__Main.SelectedTab = this.tabPage__Language; break; }
				case "Derivating": { this.tabControl__Main.SelectedTab = this.tabPage__Derivating; break; }
				case "Pattern": { this.tabControl__Main.SelectedTab = this.tabPage__Pattern; break; }
				case "Word": { this.tabControl__Main.SelectedTab = this.tabPage__Word; break; }
				case "Book": { this.tabControl__Main.SelectedTab = this.tabPage__Book; break; }
				case "Hierarchy": { this.tabControl__Main.SelectedTab = this.tabPage__Hierarchy; break; }
				case "System": { this.tabControl__Main.SelectedTab = this.tabPage__System; break; }
				default: { this.tabControl__Main.SelectedTab = this.tabPage__Language; break; }
			}

			#endregion	focus the lastly-used TabPage.
			#region		build GuiTables

			#region		DerivatingWordType_DerivatedWordType

			this.guiTable__DerivatingWordType_DerivatedWordType = new GuiTable__DerivatingWordType_DerivatedWordType(this);

			this.guiTable__DerivatingWordType_DerivatedWordType.RowChanged += GuiTable__DerivatingWordType_DerivatedWordType__RowChanged;

			this.BindingSource__DerivatingWordType_DerivatedWordType
				= new BindingSource
				(
					this.guiTable__DerivatingWordType_DerivatedWordType.DataSetForBindingSource,
					"DerivatingWordType_DerivatedWordType_"
				);
			this.BindingSource__DerivatingWordType_DerivatedWordType.CurrentChanged
				+= bindingSource__DerivatingWordType_DerivatedWordType__CurrentChanged;

			this.dataGridView__DerivatingWordType_DerivatedWordType.DataSource
				= this.BindingSource__DerivatingWordType_DerivatedWordType;

			#endregion	DerivatingWordType_DerivatedWordType
			#region		GuiTable__WordFromPattern__of__Current__Pattern

			this.guiTable__WordFromPattern__of__Current__Pattern = new GuiTable__WordFromPattern__of__Current__Pattern(this);

			this.BindingSource__WordFromPattern__of__Current__Pattern
				= new BindingSource
				(
					this.guiTable__WordFromPattern__of__Current__Pattern.DataSet__for__MainForm__BindingSource,
					this.guiTable__WordFromPattern__of__Current__Pattern.TableName											// "WordFromPattern__of__Current__Pattern_"
				);

			this.DataGridView__Pattern__Children__WordFromPattern.DataSource
				= this.BindingSource__WordFromPattern__of__Current__Pattern;

			this.DataGridView__Pattern__Children__WordFromPattern
				.Sort
				(
					this.DataGridView__Pattern__Children__WordFromPattern.Columns[6], // this.dataGridViewTextBoxColumn__Pattern__Children__WordFromPattern__SORTING, 
					ListSortDirection.Ascending
				);

			this.BindingSource__WordFromPattern__of__Current__Pattern.CurrentChanged
				+= bindingSource__WordFromPattern__of__Current__Pattern__CurrentChanged;

			#endregion	GuiTable__WordFromPattern__of__Current__Pattern
			#region		GuiTable__PatternFromPattern__of__Current__Pattern

			this.guiTable__PatternFromPattern__of__Current__Pattern = new GuiTable__PatternFromPattern__of__Current__Pattern(this);

			this.BindingSource__PatternFromPattern__of__Current__Pattern
				= new BindingSource
				(
					this.guiTable__PatternFromPattern__of__Current__Pattern.DataSet__for__MainForm__BindingSource,
					this.guiTable__PatternFromPattern__of__Current__Pattern.TableName										///	"PatternFromPattern__of__Current__Pattern_"
				);

			this.dataGridView__Pattern__Children__PatternFromPattern.DataSource
				= this.BindingSource__PatternFromPattern__of__Current__Pattern;

			this.dataGridView__Pattern__Children__PatternFromPattern
				.Sort
				(
					this.dataGridView__Pattern__Children__PatternFromPattern.Columns[5], // this.dataGridViewTextBoxColumn__Pattern__Children__PatternFromPattern__SORTING, 
					ListSortDirection.Ascending
				);

			this.BindingSource__PatternFromPattern__of__Current__Pattern.CurrentChanged
				+= bindingSource__PatternFromPattern__of__Current__Pattern__CurrentChanged;

			#endregion	GuiTable__PatternFromPattern__of__Current__Pattern
			#region		WordByInsertion__of__Current__Word

			this.guiTable__WordByInsertion__of__Current__Word = new GuiTable__WordByInsertion__of__Current__Word(this);

			this.BindingSource__WordByInsertion__of__Current__Word
				= new BindingSource
				(
					this.guiTable__WordByInsertion__of__Current__Word.DataSet__for__MainForm__BindingSource,
					this.guiTable__WordByInsertion__of__Current__Word.TableName
				);
			this.BindingSource__WordByInsertion__of__Current__Word.CurrentChanged
				+= bindingSource__WordByInsertion__of__Current__Word__CurrentChanged;

			this.DataGridView__ChildWords__ByInsertion.DataSource
				= this.BindingSource__WordByInsertion__of__Current__Word;

			#endregion	WordByInsertion__of__Current__Word
			#region		PatternByInsertion__of__Current__Word

			this.guiTable__PatternByInsertion__of__Current__Word = new GuiTable__PatternByInsertion__of__Current__Word(this);

			this.BindingSource__PatternByInsertion__of__Current__Word
				= new BindingSource
				(
					this.guiTable__PatternByInsertion__of__Current__Word.DataSet__for__MainForm__BindingSource,
					this.guiTable__PatternByInsertion__of__Current__Word.TableName
				);
			this.BindingSource__PatternByInsertion__of__Current__Word.CurrentChanged
			  += bindingSource__PatternByInsertion__of__Current__Word__CurrentChanged;

			this.DataGridView__PatternByInsertion__of__Current__Word.DataSource
				= this.BindingSource__PatternByInsertion__of__Current__Word;

			#endregion	PatternByInsertion__of__Current__Word
			#region		PatternByInsertion__of__Current__Pattern

			this.guiTable__PatternByInsertion__of__Current__Pattern = new GuiTable__PatternByInsertion__of__Current__Pattern(this);

			this.BindingSource__PatternByInsertion__of__Current__Pattern
				= new BindingSource
				(
					this.guiTable__PatternByInsertion__of__Current__Pattern.DataSet__for__MainForm__BindingSource,
					this.guiTable__PatternByInsertion__of__Current__Pattern.TableName
				);
			this.BindingSource__PatternByInsertion__of__Current__Pattern.CurrentChanged
			  += bindingSource__PatternByInsertion__of__Current__Pattern__CurrentChanged;

			       this.dataGridView__PatternByInsertion__of__Current__Pattern.DataSource
				= this.BindingSource__PatternByInsertion__of__Current__Pattern;

			#endregion	PatternByInsertion__of__Current__Pattern
			#region		WordDerivated__of__WordDerivating

			this.guiTable__WordDerivated__of__WordDerivating = new GuiTable__WordDerivated__of__WordDerivating(this);

			this.BindingSource__WordDerivated__of__WordDerivating
				= new BindingSource
				(
					this.guiTable__WordDerivated__of__WordDerivating.DataSet__for__MainForm__BindingSource,
					this.guiTable__WordDerivated__of__WordDerivating.TableName								// "WordDerivated__of__WordDerivating_"
				);
			this.BindingSource__WordDerivated__of__WordDerivating.CurrentChanged
				+= bindingSource__WordDerivated__of__WordDerivating__CurrentChanged;

			this.DataGridView__WordDerivated__of__WordDerivating.DataSource
				= this.BindingSource__WordDerivated__of__WordDerivating;

			#endregion	WordDerivated__of__WordDerivating
			#region		WordConcatenatedComponent

			this.guiTable__WordConcatenatedComponent = new GuiTable__WordConcatenatedComponent(this);

			this.BindingSource__WordConcatenatedComponent
				= new BindingSource
				(
					this.guiTable__WordConcatenatedComponent.DataSet__for_the_BindingSource,
					"WordConcatenatedComponent_"
				);
			this.BindingSource__WordConcatenatedComponent.CurrentChanged
				+= bindingSource__WordConcatenatedComponent__CurrentChanged;

			this.dataGridView__WordConcatenatedComponent.DataSource
				= this.BindingSource__WordConcatenatedComponent;

			#endregion	WordConcatenatedComponent
			#region		WordConcatenating

			this.guiTable__WordConcatenating = new GuiTable__WordConcatenating(this);

			this.BindingSource__WordConcatenating = new BindingSource(this.guiTable__WordConcatenating.DataSetForBindingSource, "WordConcatenating_");
			this.BindingSource__WordConcatenating.CurrentChanged += bindingSource__WordConcatenating__CurrentChanged;

			this.dataGridView__WordConcatenating.DataSource = this.BindingSource__WordConcatenating;

			#endregion	WordConcatenating
			#region		BookSentence

			this.guiTable__BookSentence = new GuiTable__BookSentence(this);

			this.bindingSource__BookSentence = new BindingSource(this.guiTable__BookSentence.DataSet__for__BindingSource, "BookSentence_");
			this.bindingSource__BookSentence.CurrentChanged += bindingSource__BookSentence__CurrentChanged;

			this.dataGridView__Book__Sentence.DataSource = this.bindingSource__BookSentence;

			#endregion	BookSentence
			#region		Sentence__LanguageLanguageword

			this.bindingSource__Sentence_LanguageLanguageWord.CurrentChanged += bindingSource__Sentence_LanguageLanguageWord_CurrentChanged;	

			#endregion	Sentence__LanguageLanguageword
			#region		guiTable__SentenceWord_LanguageWord

			this.guiTable__SentenceWord = new GuiTable__SentenceWord(this);

			this.bindingSource__SentenceWord = new BindingSource(this.guiTable__SentenceWord.DataSet__for__BindingSource, "SentenceWord_");
			this.bindingSource__SentenceWord.CurrentChanged += bindingSource__SentenceWord_LanguageWord__CurrentChanged;

			this.dataGridView__Book__SentenceWord.DataSource = this.bindingSource__SentenceWord;

			this.dataGridView__Book__SentenceWord.Sort(this.dataGridView__Book__SentenceWord.Columns[1], ListSortDirection.Ascending);

			#endregion	guiTable__SentenceWord_LanguageWord

			#endregion	build GuiTables
			#region		focus last focused row for each grid.

			#region		Language

			string current__Language__Code = Properties.Settings.Default.PK__Language__Code;

			if (!string.IsNullOrEmpty(current__Language__Code))
			{
				this.Current__Language = this.DataSet.Language.FindByCode(current__Language__Code);

				if (this.Current__Language != null)
				{
					FocusGridRow(this.bindingSource__Language, this.Current__Language, out bool? hasFocusedRowChanged);

					if (!hasFocusedRowChanged.Value)
					{
						this.currentChanged__Language();
					}
				}
			}

			#endregion	Language
			#region		LetterOrSymbol_Language

			string current__LetterOrSymbol_Language__LetterString = Properties.Settings.Default.PK__LetterOrSymbol_Language__LetterString;

			if (!string.IsNullOrEmpty(current__LetterOrSymbol_Language__LetterString))
			{
				this.Current__LetterOrSymbol_Language
					= this.DataSet.LetterOrSymbol_Language
					.FindByLetterOrSymbolStringLanguageCode
					(
						current__LetterOrSymbol_Language__LetterString,
						current__Language__Code
					);

				if (this.Current__LetterOrSymbol_Language != null)
				{

					FocusGridRow(this.bindingSource__LetterOrSymbol_Language, this.Current__LetterOrSymbol_Language);
				}
			}

			#endregion	LetterOrSymbol_Language
			#region		DerivatingWordType_Language

			short? current__DerivatingWordType_Language__DerivatingWordTypeId
				= Properties.Settings.Default.PK__DerivatingWordType__Id;

			if (current__DerivatingWordType_Language__DerivatingWordTypeId != 0)
			{
				this.Current__DerivatingWordType
					= this.DataSet.DerivatingWordType.FindById(current__DerivatingWordType_Language__DerivatingWordTypeId.Value);

				this.Current__DerivatingWordType_Language
					= this.DataSet.DerivatingWordType_Language
					.FindByDerivatingWordTypeIdLanguageCode
					(
						current__DerivatingWordType_Language__DerivatingWordTypeId.Value,
						this.Current__Language.Code
					);


				if (this.Current__DerivatingWordType_Language != null)
				{
					this.Current__DerivatingWordType = this.Current__DerivatingWordType_Language.DerivatingWordTypeRowParent;


					FocusGridRow(this.bindingSource__DerivatingWordType_Language, this.Current__DerivatingWordType_Language);
				}
			}

			#endregion	DerivatingWordType_Language
			#region		DerivatedWordType_Language

			short? current__DerivatedWordType_Language__DerivatedWordTypeId
				= Properties.Settings.Default.PK__DerivatedWordType__Id;

			if (current__DerivatedWordType_Language__DerivatedWordTypeId != 0)
			{
				this.Current__DerivatedWordType
					= this.DataSet.DerivatedWordType.FindById(current__DerivatedWordType_Language__DerivatedWordTypeId.Value);

				this.Current__DerivatedWordType_Language
					= this.DataSet.DerivatedWordType_Language
					.FindByDerivatedWordTypeIdLanguageCode(current__DerivatedWordType_Language__DerivatedWordTypeId.Value, this.Current__Language.Code);


				if (this.Current__DerivatedWordType_Language != null)
				{
					this.Current__DerivatedWordType = this.Current__DerivatedWordType_Language.DerivatedWordTypeRowParent;


					FocusGridRow(this.bindingSource__DerivatedWordType_Language, this.Current__DerivatedWordType_Language);
				}
			}

			#endregion	DerivatedWordType_Language
			#region		DerivatingWordType_DerivatedWordType (GuiTable)

			this.guiTable__DerivatingWordType_DerivatedWordType.Populate();

			if (this.Current__DerivatingWordType != null)
			{
				this.BindingSource__DerivatingWordType_DerivatedWordType.Filter = "DerivatingWordTypeId = '" + this.Current__DerivatingWordType.Id + "'";

				if (this.Current__DerivatedWordType != null)
				{
					DataRow dataRow
						= this.guiTable__DerivatingWordType_DerivatedWordType.Find(this.Current__DerivatingWordType.Id, this.Current__DerivatedWordType.Id);


					if (FocusGridRow(this.BindingSource__DerivatingWordType_DerivatedWordType, dataRow))
					{
						this.Current__DerivatingWordType_DerivatedWordType
							= this.DataSet.DerivatingWordType_DerivatedWordType
							.FindByDerivatingWordTypeIdDerivatedWordTypeId
							(
								this.Current__DerivatingWordType.Id,
								this.Current__DerivatedWordType.Id
							);

						string bindingSource__Derivating_Language__Filter = "";
						bindingSource__Derivating_Language__Filter += "DerivatingWordTypeId = '" + this.Current__DerivatingWordType.Id.ToString() + "'";
						bindingSource__Derivating_Language__Filter += " AND ";
						bindingSource__Derivating_Language__Filter += "DerivatedWordTypeId = '" + this.Current__DerivatedWordType.Id.ToString() + "'";
						bindingSource__Derivating_Language__Filter += " AND ";
						bindingSource__Derivating_Language__Filter += "LanguageCode = '" + this.Current__Language.Code + "'";

						this.bindingSource__Derivating_Language.Filter = bindingSource__Derivating_Language__Filter;
					}
				}

			}

			#endregion	build GuiTables and bind them to their respective DataGridViews.
			#region		Derivating_Language

			short? current__Derivating_Language__DerivatingId
				= Properties.Settings.Default.PK__Derivating__Id;

			if (current__Derivating_Language__DerivatingId != 0)
			{
				this.Current__Derivating
					= this.DataSet.Derivating
					.FindById(current__Derivating_Language__DerivatingId.Value);

				this.Current__Derivating_Language
					= this.DataSet.Derivating_Language
					.FindByDerivatingIdLanguageCode
					(
						current__Derivating_Language__DerivatingId.Value,
						this.Current__Language.Code
					);


				if (!FocusGridRow(this.bindingSource__Derivating_Language, this.Current__Derivating_Language))
				{
					this.Current__Derivating_Language = null;
					this.Current__Derivating = null;
				}
			}

			#endregion	Derivating_Language
			#region		Pattern_Language

			int? current__Pattern_Language__PatternId = Properties.Settings.Default.PK__Pattern__Id;

			if (current__Pattern_Language__PatternId > -1)
			{
				this.Current__Pattern_Language
					= this.DataSet.Pattern_Language
					.FindByPatternIdLanguageCode
					(
						current__Pattern_Language__PatternId.Value,
						this.Current__Language.Code
					);

				if (this.Current__Pattern_Language != null)
				{
					this.Current__Pattern
						= this.Current__Pattern_Language.PatternRow;

					this.populate__Pattern();
				}
				else
				{
					this.display__no__Pattern();
				}
			}
			else
			{
				this.display__no__Pattern();
			}

			#endregion	Pattern_Language
			#region		Word_Language

			int? current__Word_Language__WordId = Properties.Settings.Default.PK__Word__Id;

			if (current__Word_Language__WordId != 0)
			{
				this.Current__Word_Language
					= this.DataSet.Word_Language
					.FindByWordIdLanguageCode
					(
						current__Word_Language__WordId.Value,
						this.Current__Language.Code
					);


				if (this.Current__Word_Language != null)
				{
					this.Current__Word
						= this.Current__Word_Language.WordRowParent;

					this.populate__Word();
				}
				else
				{
					this.Current__Word = null;

					this.comboBox__Word__Extension.SelectedItem = MainForm.ModeName_NotDefined;

					this.comboBox__Word__Extension.Enabled = false;

					this.button__WordDerivating__Append.Enabled = false;
					this.button__WordDerivating__Remove.Enabled = false;
				}
			}
			else
			{
				this.Current__Word_Language = null;
				this.Current__Word = null;

				this.comboBox__Word__Extension.SelectedItem = ModeName_NotDefined;

				this.comboBox__Word__Extension.Enabled = false;

				this.button__WordDerivating__Append.Enabled = false;
				this.button__WordDerivating__Remove.Enabled = false;
			}

			this.filter__Word_LanguageWord__of__Word();

			#endregion	Word_Language
			#region		Word_LanguageWord__of__Word

			string current__Word_LanguageWord__of__Word__LanguageWordString = Properties.Settings.Default.PK__Word_LanguageWord__of__Word__LanguageWordString;

			if
			(
				this.Current__Language != null
				&&
				this.Current__Word != null
				&&
				!string.IsNullOrEmpty(current__Word_LanguageWord__of__Word__LanguageWordString)
			)
			{
				this.Current__Word_LanguageWord__of__Word
					= this.DataSet.Word_LanguageWord
					.FindByWordIdLanguageCodeLanguageWordString
					(
						this.Current__Word.Id,
						this.Current__Language.Code,
						current__Word_LanguageWord__of__Word__LanguageWordString
					);

				if (this.Current__Word_LanguageWord__of__Word != null)
				{

					if (!MainForm.FocusGridRow(this.bindingSource__Word_LanguageWord__of__Word, this.Current__Word_LanguageWord__of__Word))
					{
						this.Current__Word_LanguageWord__of__Word = null;
					}
				}
			}

			#endregion	Word_LanguageWord__of__Word
			#region		LanguageWord

			string current__LanguageWord__String = Properties.Settings.Default.PK__LanguageWord__String;


			if (this.Current__Language == null )
			{
				if (!string.IsNullOrEmpty(current__LanguageWord__String))
				{ 
					this.Current__LanguageWord
						= this.DataSet.LanguageWord
						.FindByLanguageCodeString
						(
							this.Current__Language.Code,
							current__LanguageWord__String
						);

					if (this.Current__LanguageWord != null)
					{
						this.textBox__LanguageWord__String.Text = this.Current__LanguageWord.String;
					}
				}
			}

			#region		(ancienne version)
			/*
			if
			(
				this.Current__Language != null
				&&
				!string.IsNullOrEmpty(current__LanguageWord__String)
			)
			{
				this.Current__LanguageWord
					= this.DataSet.LanguageWord
					.FindByLanguageCodeString
					(
						this.Current__Language.Code,
						current__LanguageWord__String
					);

				if (this.Current__LanguageWord != null)
				{
					this.textBox__LanguageWord__String.Text = this.Current__LanguageWord.String;

					this.filter__Word_LanguageWord__of__LanguageWord();
				}
			}
			else
			{
				this.bindingSource__Word_LanguageWord__of__LanguageWord.Filter = "FALSE";

				this.Current__LanguageWord = null;
			}
			*/
			#endregion	(ancienne version)

			#endregion	Word_Language
			#region		Word_LanguageWord__of__LanguageWord

			int? current__Word_LanguageWord__of__LanguageWord__WordId
				= Properties.Settings.Default
				.PK__Word_LanguageWord__of__LanguageWord__WordId;

			if
			(
				this.Current__Language != null
				&&
				this.Current__LanguageWord != null
				&&
				current__Word_LanguageWord__of__LanguageWord__WordId.HasValue
			)
			{
				this.Current__Word_LanguageWord__of__LanguageWord
					= this.DataSet.Word_LanguageWord
					.FindByWordIdLanguageCodeLanguageWordString
					(
						current__Word_LanguageWord__of__LanguageWord__WordId.Value,
						this.Current__Language.Code,
						this.Current__LanguageWord.String
					);

				if (this.Current__Word_LanguageWord__of__LanguageWord != null)
				{
					if (!MainForm.FocusGridRow(this.bindingSource__Word_LanguageWord__of__LanguageWord, this.Current__Word_LanguageWord__of__LanguageWord))
					{
						this.Current__Word_LanguageWord__of__LanguageWord = null;
					}
				}
			}
			else
			{
				this.Current__Word_LanguageWord__of__LanguageWord = null;
			}

			#endregion	Word_LanguageWord__of__LanguageWord
			#region		WordByInsertion__of__Current__Word

			if 
			(
				this.Current__Word != null 
				&& 
				this.Current__Word.GetWordByInsertionRowsByWordByInsertion__Word__Origin().Length > 0
			)
			{
				int current__WordByInsertion__of__Current__Word
					= Properties.Settings.Default.PK__WordByInsertion__of__Current__Word__Id;

				if (current__WordByInsertion__of__Current__Word != 0)
				{
					DataRow guiDataRow 
						= this.guiTable__WordByInsertion__of__Current__Word
						.Find(current__WordByInsertion__of__Current__Word);

					if (guiDataRow != null)
					{
						FocusGridRow(this.BindingSource__WordByInsertion__of__Current__Word, guiDataRow);
					}
				}
			}

			#endregion	WordByInsertion__of__Current__Word
			#region		WordDerivated__of__WordDerivating

			if (this.Current__Word != null && this.Current__Word.GetWordDerivatingRows().Length > 0)
			{
				int current__WordDerivated__of__WordDerivating__Id
					= Properties.Settings.Default.PK__WordDerivated__of__WordDerivating__Id;

				if (current__WordDerivated__of__WordDerivating__Id != 0)
				{
					this.Current__WordDerivated__of__WordDerivating
						= this.DataSet.WordDerivated.FindById(current__WordDerivated__of__WordDerivating__Id);

					if (this.Current__WordDerivated__of__WordDerivating != null)
					{
						DataRow guiDataRow = this.guiTable__WordDerivated__of__WordDerivating.Find(this.Current__WordDerivated__of__WordDerivating.Id);

						if (guiDataRow != null)
						{
							FocusGridRow(this.BindingSource__WordDerivated__of__WordDerivating, guiDataRow);
						}
					}
				}
			}

			#endregion	WordDerivated__of__WordDerivating
			#region		WordConcatenating

			if (this.Current__Word != null && this.Current__Word.GetWordConcatenatedComponentRows().Length > 0)
			{
				int current__WordConcatenating__WordConcatenatedId = Properties.Settings.Default.PK__WordConcatenating__WordConcatenatedId;
				short current__WordConcatenating__Rank = Properties.Settings.Default.PK__WordConcatenating__Rank;

				if (current__WordConcatenating__WordConcatenatedId != 0 && current__WordConcatenating__Rank != 0)
				{
					this.Current__WordConcatenating
						= this.DataSet.WordConcatenatedComponent.FindByWordConcatenatedIdRank
						(
							current__WordConcatenating__WordConcatenatedId,
							current__WordConcatenating__Rank
						);

					DataRow guiDataRow = this.guiTable__WordConcatenating.Find(this.Current__WordConcatenating);

					if (guiDataRow != null)
					{
						FocusGridRow(this.BindingSource__WordConcatenating, guiDataRow);
					}
				}
			}

			#endregion	WordConcatenating
			#region		Book

			int		book__Id						= Properties.Settings.Default.PK__Book__Id;
			int		bookSentence__Index				= Properties.Settings.Default.PK__BookSentence__Index;
			short	bookSentenceLanguageWordIndex	= Properties.Settings.Default.PK__Book__SentenceLanguageWord__Index;
			short	bookSentenceWordIndex			= Properties.Settings.Default.PK__Book__SentenceWord__Index;

			this.populate__Book
				(
					book__Id,
					bookSentence__Index,
					bookSentenceLanguageWordIndex,
					bookSentenceWordIndex
				);

			if (this.Current__Book != null && this.Current__BookSentence != null)
			{
				DataRow guiDataRow = this.guiTable__BookSentence.Find(bookSentence__Index);
				FocusGridRow(this.bindingSource__BookSentence, guiDataRow);
			}

			#endregion	Book	

			#endregion	focus last focused row for each grid.
			#region		load Hierarchy TreeView

			/// story : on initialise the TV avec les Patterns qui ne sont pas des Childs.

			foreach (BabebiDataSet.PatternExNihiloRow patternExNihilo in this.DataSet.PatternExNihilo)
			{
				BabebiDataSet.Pattern_LanguageRow pattern_Language
					= this.DataSet.Pattern_Language
					.FindByPatternIdLanguageCode
					(
						patternExNihilo.Id, 
						this.Current__Language.Code
					);

				string uniqueKeyString	= patternExNihilo.PatternRowParent.UniqueKeyString;
				string meaning			= pattern_Language.Meaning;

				TreeNode treeNode = new TreeNode("[" + uniqueKeyString + "] : '" + meaning + "'");

				treeNode.Tag = new TreeViewNodeTag__PatternExNihilo(this, patternExNihilo);

				this.treeView__Hierarchy.Nodes.Add(treeNode);
			}

			#endregion	load Hierarchy TreeView
			#region		get prior LanguageWord candidates that are automatically identified as being rejected.

			string notLanguageWordCandidatesString = Properties.Settings.Default.NotLanguageWordCandidates;

			if (notLanguageWordCandidatesString != "")
			{
				string[] notLanguageWordCandidates = notLanguageWordCandidatesString.Split('#');

				this.SubStrings__registered_as_being_not_LanguageWords_forever
					= new List<string>(notLanguageWordCandidates);
			}
			else
			{ 
				this.SubStrings__registered_as_being_not_LanguageWords_forever = new List<string>();
			}

			#endregion	get prior LanguageWord candidates that are automatically identified as being rejected.
		}

		private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
		{
			#region		save the dataSet in the xml file.

			if (this.DataSet.HasChanges())
			{
				DialogResult dialogResult = MessageBox.Show("Do you want to save your modification ?", "Save or not ?", MessageBoxButtons.YesNoCancel);

				if (dialogResult == DialogResult.Cancel)
				{
					return;
				}
				else if (dialogResult == DialogResult.Yes)
				{
					this.DoNotTriggerCurrentChangedEvent = true;
					this.DataSet.AcceptChanges();

					this.DataSet.WriteXml(this.currentXmlFilesDirectoryFullName + "\\BabebiDataSet_" + DateTime.Now.ToString("yyyy_MM_dd_HHmmss") + ".xml");
					this.DoNotTriggerCurrentChangedEvent = false;
				}
				else if (dialogResult == DialogResult.No)
				{
				}
				else
				{
					throw new Exception();
				}
			}

			#endregion	save the dataSet in the xml file.
			#region		register the focused TabPage.

			string selectedTabText = this.tabControl__Main.SelectedTab.Text.Trim();

			BabebiDataSet.LanguageRow foundLanguage = this.DataSet.Language.FindByCode(selectedTabText.ToLower());
			if (foundLanguage != null)
			{
				Properties.Settings.Default.FocusedTabPage = "Language";
			}
			else
			{
				Properties.Settings.Default.FocusedTabPage = selectedTabText;
			}

			#endregion	register the focused TabPage.
			#region		save grid row focusing.

			#region		Language

			if (this.Current__Language != null)
			{
				Properties.Settings.Default.PK__Language__Code = this.Current__Language.Code;
			}

			#endregion	Language
			#region		LetterOrSymbol_Language

			if (this.Current__LetterOrSymbol_Language != null)
			{
				Properties.Settings.Default.PK__LetterOrSymbol_Language__LetterString = this.Current__LetterOrSymbol_Language.LetterOrSymbolString;
			}

			#endregion	LetterOrSymbol_Language
			#region		DerivatingWordType_Language

			if (this.Current__DerivatingWordType_Language != null)
			{
				Properties.Settings.Default.PK__DerivatingWordType__Id = this.Current__DerivatingWordType_Language.DerivatingWordTypeId;
			}

			#endregion	DerivatingWordType_Language
			#region		DerivatedWordType_Language

			if (this.Current__DerivatedWordType_Language != null)
			{
				Properties.Settings.Default.PK__DerivatedWordType__Id = this.Current__DerivatedWordType_Language.DerivatedWordTypeId;
			}

			#endregion	DerivatedWordType_Language
			#region		Derivating_Language

			if (this.Current__Derivating != null && this.Current__Derivating.RowState != DataRowState.Detached && this.Current__Derivating.RowState != DataRowState.Deleted)
			{
				Properties.Settings.Default.PK__Derivating__Id = this.Current__Derivating.Id;
			}

			#endregion	Derivating_Language
			#region		Pattern_Language

			if (this.Current__Pattern != null && this.Current__Pattern.RowState != DataRowState.Detached && this.Current__Pattern.RowState != DataRowState.Deleted)
			{
				Properties.Settings.Default.PK__Pattern__Id = this.Current__Pattern.Id;
			}

			#endregion	Word_Language
			#region		Word_Language

			if (this.Current__Word != null && this.Current__Word.RowState != DataRowState.Detached && this.Current__Word.RowState != DataRowState.Deleted)
			{
				Properties.Settings.Default.PK__Word__Id = this.Current__Word.Id;
			}

			#endregion	Word_Language
			#region		LanguageWord

			if
			(
				this.Current__LanguageWord != null
				&&
				this.Current__LanguageWord.RowState != DataRowState.Detached
				&&
				this.Current__LanguageWord.RowState != DataRowState.Deleted
			)
			{
				Properties.Settings.Default.PK__LanguageWord__String = this.Current__LanguageWord.String;
			}

			#endregion	LanguageWord
			#region		Word_LanguageWord__of__Word

			if
			(
				this.Current__Word_LanguageWord__of__Word != null
				&&
				this.Current__Word_LanguageWord__of__Word.RowState != DataRowState.Detached
				&&
				this.Current__Word_LanguageWord__of__Word.RowState != DataRowState.Deleted
			)
			{
				Properties.Settings.Default.PK__Word_LanguageWord__of__Word__LanguageWordString = this.Current__Word_LanguageWord__of__Word.LanguageWordString;
			}

			#endregion	Word_LanguageWord__of__Word
			#region		Word_LanguageWord__of__LanguageWord

			if
			(
				this.Current__Word_LanguageWord__of__LanguageWord != null
				&&
				this.Current__Word_LanguageWord__of__LanguageWord.RowState != DataRowState.Detached
				&&
				this.Current__Word_LanguageWord__of__LanguageWord.RowState != DataRowState.Deleted
			)
			{
				Properties.Settings.Default.PK__Word_LanguageWord__of__LanguageWord__WordId = this.Current__Word_LanguageWord__of__LanguageWord.WordId;
			}

			#endregion	Word_LanguageWord__of__Word
			#region		WordChild__of__WordParent

			if
			(
				this.Current__WordByInsertion__of__Current__Word != null
				&&
				this.Current__WordByInsertion__of__Current__Word.RowState != DataRowState.Detached
				&&
				this.Current__WordByInsertion__of__Current__Word.RowState != DataRowState.Deleted
			)
			{
				Properties.Settings.Default.PK__WordByInsertion__of__Current__Word__Id = this.Current__WordByInsertion__of__Current__Word.Id;
			}
			else
			{
				Properties.Settings.Default.PK__WordByInsertion__of__Current__Word__Id = 0;
			}

			#endregion	WordChild__of__WordParent
			#region		WordDerivated__of__WordDerivating

			if
			(
				this.Current__WordDerivated__of__WordDerivating != null
				&&
				this.Current__WordDerivated__of__WordDerivating.RowState != DataRowState.Detached
				&&
				this.Current__WordDerivated__of__WordDerivating.RowState != DataRowState.Deleted
			)
			{
				Properties.Settings.Default.PK__WordDerivated__of__WordDerivating__Id = this.Current__WordDerivated__of__WordDerivating.Id;
			}
			else
			{
				Properties.Settings.Default.PK__WordDerivated__of__WordDerivating__Id = 0;
			}

			#endregion	WordDerivated__of__WordDerivating
			#region		WordConcatenating

			if
			(
				this.Current__WordConcatenating != null
				&&
				this.Current__WordConcatenating.RowState != DataRowState.Detached
				&&
				this.Current__WordConcatenating.RowState != DataRowState.Deleted
			)
			{
				Properties.Settings.Default.PK__WordConcatenating__WordConcatenatedId = this.Current__WordConcatenating.WordConcatenatedId;
				Properties.Settings.Default.PK__WordConcatenating__Rank = this.Current__WordConcatenating.Rank;
			}
			else
			{
				Properties.Settings.Default.PK__WordConcatenating__WordConcatenatedId = 0;
				Properties.Settings.Default.PK__WordConcatenating__Rank = 0;
			}

			#endregion	WordConcatenating
			#region		Book

			if
			(
				this.Current__Book != null
				&&
				this.Current__Book.RowState != DataRowState.Detached
				&&
				this.Current__Book.RowState != DataRowState.Deleted
			)
			{
				Properties.Settings.Default.PK__Book__Id	= this.Current__Book.Id;
			}
			else
			{
				Properties.Settings.Default.PK__Book__Id = 0;
			}

			if
			(
				this.Current__BookSentence != null
				&&
				this.Current__BookSentence.RowState != DataRowState.Detached
				&&
				this.Current__BookSentence.RowState != DataRowState.Deleted
			)
			{
				Properties.Settings.Default.PK__BookSentence__Index	= this.Current__BookSentence.Index;
			}
			else
			{
				Properties.Settings.Default.PK__BookSentence__Index = 0;
			}

			if
			(
				this.Current__SentenceWord != null
				&&
				this.Current__SentenceWord.RowState != DataRowState.Detached
				&&
				this.Current__SentenceWord.RowState != DataRowState.Deleted
			)
			{
				Properties.Settings.Default.PK__Book__SentenceWord__Index	= this.Current__SentenceWord.Index;
			}
			else
			{
				Properties.Settings.Default.PK__Book__SentenceWord__Index = 0;
			}

			if
			(
				this.Current__Sentence_LanguageLanguageWord != null
				&&
				this.Current__Sentence_LanguageLanguageWord.RowState != DataRowState.Detached
				&&
				this.Current__Sentence_LanguageLanguageWord.RowState != DataRowState.Deleted
			)
			{
				Properties.Settings.Default.PK__Book__SentenceLanguageWord__Index	= this.Current__Sentence_LanguageLanguageWord.Index;
			}
			else
			{
				Properties.Settings.Default.PK__Book__SentenceLanguageWord__Index = 0;
			}

			#endregion	Book

			#region		register prior LanguageWord candidates that are automatically identified as being rejected.

			string notLanguageWordCandidatesString = "";

			foreach(string s in this.SubStrings__registered_as_being_not_LanguageWords_forever)
			{
				notLanguageWordCandidatesString += (notLanguageWordCandidatesString == "" ? "" : "#") + s; 
			}

			Properties.Settings.Default.NotLanguageWordCandidates = notLanguageWordCandidatesString;

			string sss = Properties.Settings.Default.NotLanguageWordCandidates;

			#endregion	register prior LanguageWord candidates that are automatically identified as being rejected.

			Properties.Settings.Default.Save();

			#endregion	save grid row focusing.
		}

		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
		{
			if (keyData == (Keys.S | Keys.Control))
			{ 
				if (this.DataSet.HasChanges())
				{
					//DataSet ds = this.DataSet.GetChanges();
					//foreach (DataTable dataTable in ds.Tables)
					//{
					//	if (dataTable.Rows.Count > 0)
					//	{
					//		continue;
					//	}
					//}

					DialogResult dialogResult = MessageBox.Show("Do you want to save your modification ?", "Save or not ?", MessageBoxButtons.YesNo);
					if (dialogResult != DialogResult.No)
					{
						this.DoNotTriggerCurrentChangedEvent = true;
						this.DataSet.AcceptChanges();

						this.DataSet.WriteXml(this.currentXmlFilesDirectoryFullName + "\\BabebiDataSet_" + DateTime.Now.ToString("yyyy_MM_dd_HHmmss") + ".xml");
						this.DoNotTriggerCurrentChangedEvent = false;
					}
				}

				return false;
			}
			else if (keyData == (Keys.W | Keys.Control))
			{
				if (this.tabControl__Main.SelectedTab == this.tabPage__Word)
				{
					MessageBox.Show("", "", MessageBoxButtons.OK);
				}

				return false;
			}
			return base.ProcessCmdKey(ref msg, keyData);


			// if ((keyData & (Keys.S | Keys.Control)) == (Keys.S | Keys.Control))
		}

		#endregion	MainForm Load & Close

		#region		Toolbox (static functions)

		public static void ShowSelectedTabPageInTabControl(TabControl tabControl, TabPage selectedTabPage, params TabPage[] tabPages__toBeRemoved)
		{
			if (selectedTabPage != null && !tabControl.TabPages.Contains(selectedTabPage))
			{
				tabControl.TabPages.Add(selectedTabPage);
			}

			foreach (TabPage tabPage__toBeRemove in tabPages__toBeRemoved)
			{
				if (tabControl.TabPages.Contains(tabPage__toBeRemove))
				{
					tabControl.TabPages.Remove(tabPage__toBeRemove);
				}
			}
		}

		/// <summary>
		/// TODO : je ne fais plus comme cela maintenant => j'utilise la nouvelle classe Error
		/// </summary>
		/// <param name="priorOrFullPrimaryKeyValues">
		/// Concernant le problème d'unicité :
		/// 
		/// Soit on est dans le cas dataColumn.Unique == true, alors on doit :
		/// - lors d'un CREATE, on ne fournit pas priorOrFullPrimaryKeyValues (pour return false dès qu'une row existante a été trouvée),
		/// - lors d'un UPDATE, on fournit priorOrFullPrimaryKeyValues = fullPrimaryKeyValues (pour faire un Find et retourner false si LA row trouvée n'est pas la row où s'effectue l'UPDATE).
		///
		/// Soit on est dans le cas dataColumn est élément d'une Constrainte. Dans ce cas on doit avoir PK.Length = priorOrFullPrimaryKeyValues.Length + 1, forcément.
		/// Si la contrainte est la PK, on peut faire un Find.
		/// Dans le cas d'un CREATE, on ne doit pas trouver de row (Select.Lenght == 0).
		/// Dans le cas d'un UPDATE (de la dernière column d'une PK), pareil : on ne doit pas trouver de row déjà existante (Select.Lenght == 0).
		/// 
		/// Si la contrainte N'est PAS la PK, on doit faire Select compliqué.
		/// Dans le cas d'un CREATE, on ne doit pas trouver de row (Select.Lenght == 0).
		/// Dans le cas d'un UPDATE (de la dernière column d'une PK), pareil : on ne doit pas trouver de row déjà existante (Select.Lenght == 0).
		/// </param>
		/// <returns>false if user entry error.</returns>
		public static bool UserEntryChecking(DataColumn dataColumn, string value, params object[] priorOrFullPrimaryKeyValues)
		{
			if (!dataColumn.AllowDBNull && string.IsNullOrEmpty(value) && dataColumn.DefaultValue == null)
			{
				MessageBox.Show("The '" + dataColumn.ColumnName + "' of a '" + dataColumn.Table.TableName + "' can not be empty.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			}

			if (dataColumn.DataType == typeof(string))
			{
				if (value.Length > dataColumn.MaxLength)
				{
					MessageBox.Show
					(
						"The maximum length of the '" + dataColumn.ColumnName + "' of a '" + dataColumn.Table.TableName + "' is " + dataColumn.MaxLength.ToString() + " " +
						"(the length of the provided value is '" + value.Length.ToString() + "')."
						, "Error",
						MessageBoxButtons.OK,
						MessageBoxIcon.Error
					);

					return false;
				}
			}

			if (dataColumn.Unique)
			{
				#region		Unique

				DataRow[] dataRows = dataColumn.Table.Select(dataColumn.ColumnName + " = '" + value.ToString() + "'");

				if (dataRows.Length == 0)
				{
					return true;
				}
				else if (dataRows.Length == 1)
				{
					if (dataColumn.Table.PrimaryKey.Length == priorOrFullPrimaryKeyValues.Length)
					{
						#region		=> cas d'un UPDATE

						DataRow dataRow = dataColumn.Table.Rows.Find(priorOrFullPrimaryKeyValues);

						if (dataRows[0] != dataRow)
						{
							string primaryKeyStringOfTheAlreadyExistingObject
								= buildThePrimaryKeyString(dataColumn, priorOrFullPrimaryKeyValues);

							MessageBox.Show
							(
								"The provided value '"
								+ value
								+ "' for the field '"
								+ dataColumn.ColumnName
								+ "' is already used for the existing "
								+ primaryKeyStringOfTheAlreadyExistingObject
								+ ", while it should be unique.",
								"Error",
								MessageBoxButtons.OK,
								MessageBoxIcon.Error
							);
							return false;
						}
						else
						{
							return true;
						}

						#endregion	=> cas d'un UPDATE
					}
					else if (dataColumn.Table.PrimaryKey.Length == 0)
					{
						#region		=> cas d'un CREATE

						MessageBox.Show("The provided '" + dataColumn.ColumnName + "' (" + value + ") is already existing, while it should be unique.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
						return false;

						#endregion	=> cas d'un CREATE
					}
					else
					{
						throw new Exception();
					}
				}
				else
				{
					throw new Exception();
				}

				#endregion	Unique
			}
			else
			{
				#region		La colonne appartient-elle a une des contraintes d'unicité (dont la PK) ?

				foreach (Constraint constraint in dataColumn.Table.Constraints)
				{
					if (constraint is UniqueConstraint uniqueConstraint)
					{
						bool isInUniqueConstraint = false;
						foreach (DataColumn uniqueConstraintColumn in uniqueConstraint.Columns)
						{
							if (uniqueConstraintColumn.ColumnName == dataColumn.ColumnName)
							{
								isInUniqueConstraint = true;
								break;
							}
						}

						if (!isInUniqueConstraint)
						{
							continue;
						}

						#region		vérifie que la colonne est bien la dernière colonne de la constrainte.

						if (dataColumn.ColumnName != uniqueConstraint.Columns.Last().ColumnName)
						{
							throw new Exception("The provided column (" + dataColumn.ColumnName + ") is not the last column of the unique constraint (" + uniqueConstraint.ConstraintName + ").");
						}

						#endregion	vérifie que la colonne est bien la dernière colonne de la constrainte.

						List<object> uniqueValueList = new List<object>(priorOrFullPrimaryKeyValues) { value }; /// puissant...
						object[] uniqueValueArray = uniqueValueList.ToArray();

						#region		vérifie que le nombre de valeurs identifiantes fourni correspond bien au nombre de colonnes dans la constrainte.

						if (uniqueValueArray.Length != uniqueConstraint.Columns.Length)
						{
							throw new Exception("The number of provided identifying values is not equal to the number of columns of the unique constraint (" + uniqueConstraint.ConstraintName + ").");
						}

						#endregion	vérifie que le nombre de valeurs identifiantes fourni correspond bien au nombre de colonnes dans la constrainte.

						DataRow existingDataRow;
						if (uniqueConstraint.IsPrimaryKey)
						{
							#region		la colonne est la seule ou dernière colonne de la PK => Find(...)

							existingDataRow = dataColumn.Table.Rows.Find(uniqueValueArray);

							#endregion	la colonne est la seule ou dernière colonne de la PK => Find(...)
						}
						else
						{
							#region		la colonne est la seule ou dernière colonne d'une contrainte qui n'est pas la PK => Select("...")

							string selectString = "";

							for (int i = 0; i < uniqueConstraint.Columns.Length; i++)
							{
								selectString += (selectString == "" ? "" : " AND ") + uniqueConstraint.Columns[i].ColumnName + " = '" + uniqueValueArray[i].ToString() + "'";
							}

							DataRow[] dataRows = dataColumn.Table.Select(selectString);

							if (dataRows.Length == 0)
							{
								existingDataRow = null;
							}
							else if (dataRows.Length == 1)
							{
								existingDataRow = dataRows.First();
							}
							else
							{
								throw new Exception();
							}

							#endregion	la colonne est la seule ou dernière colonne d'une contrainte qui n'est pas la PK => Select("...")
						}

						if (existingDataRow != null)
						{
							object[] primaryKeyValues = new object[dataColumn.Table.PrimaryKey.Length];
							for (int i = 0; i < dataColumn.Table.PrimaryKey.Length; i++)
							{
								primaryKeyValues[i] = existingDataRow[i];
							}

							string primaryKeyStringOfTheAlreadyExistingObject
								= buildThePrimaryKeyString(dataColumn, primaryKeyValues);

							MessageBox.Show
							(
								"The provided value of the '" + dataColumn.ColumnName + "' field ('" + value + "') is already used by the '" + primaryKeyStringOfTheAlreadyExistingObject + "'.",
								"Error",
								MessageBoxButtons.OK,
								MessageBoxIcon.Error
							);

							return false;
						}
						else
						{
							return true;
						}
					}
				}

				return true;

				#endregion	La colonne appartient-elle a une des contraintes d'unicité (dont la PK) ?
			}
		}

		private static string buildThePrimaryKeyString(DataColumn dataColumn, object[] primaryKeyValues)
		{
			string primaryKeyStringOfTheAlreadyExistingObject = dataColumn.Table.TableName + "(";
			for (int i = 0; i < dataColumn.Table.PrimaryKey.Length; i++)
			{
				primaryKeyStringOfTheAlreadyExistingObject
					+= (primaryKeyStringOfTheAlreadyExistingObject == dataColumn.Table.TableName + "(" ? "" : ", ")
					+ dataColumn.Table.PrimaryKey[i].ColumnName
					+ " = "
					+ primaryKeyValues[i].ToString();
			}
			primaryKeyStringOfTheAlreadyExistingObject += ")";
			return primaryKeyStringOfTheAlreadyExistingObject;
		}

		/// TODO : faire une enquête : le code ci-dessus versus le code qui utilise .CurrentCell = ...
		public static bool FocusGridRow(BindingSource bindingSource, DataRow currentDataRow, out bool? hasFocusedRowChanged)
		{
			int? indexOfTheDataRowInTheGrid = null;

			foreach (var v in bindingSource.CurrencyManager.List)   //	DataRowView dataRowView
			{
				DataRow dataRow = ((DataRowView)v).Row;

				if (dataRow == currentDataRow)
				{
					indexOfTheDataRowInTheGrid = bindingSource.CurrencyManager.List.IndexOf(v);
					break;
				}
			}
			if (indexOfTheDataRowInTheGrid.HasValue)
			{
				if (bindingSource.CurrencyManager.Position != indexOfTheDataRowInTheGrid.Value)
				{
					bindingSource.CurrencyManager.Position = indexOfTheDataRowInTheGrid.Value;
					hasFocusedRowChanged = true;
				}
				else
				{
					hasFocusedRowChanged = false;
				}

				return true;
			}
			else
			{
				hasFocusedRowChanged = null;

				return false;
			}
		}
		public static bool FocusGridRow(BindingSource bindingSource, DataRow currentDataRow)
		{
			return FocusGridRow(bindingSource, currentDataRow, out bool? hasFocusedRowChanged);
		}
		public static void PropagateNaming(string name, DataColumn nameDatacolumn, DataRow currentDataRow, DataRow updatedDataRow)
		{
			if (currentDataRow == updatedDataRow)
			{
				currentDataRow[nameDatacolumn] = name;
			}
			else
			{
				if (currentDataRow[nameDatacolumn] == DBNull.Value || ((string)(currentDataRow[nameDatacolumn])).StartsWith("**"))
				{
					currentDataRow[nameDatacolumn] = "**" + (string)(updatedDataRow["LanguageCode"]) + "**" + name;
				}
				else
				{
					/// on n'y touche pas.
				}
			}
		}

		/// TODO : à virer petit à petit car visiblement moins performant qu'un Find(...).
		public DataRow DataRow__Language(DataRow dataRow)
		{
			string relationName
				= dataRow.Table.TableName
				+ "_Language__"
				+ dataRow.Table.TableName;

			string relationName__Language
				= dataRow.Table.TableName
				+ "_Language__Language";

			foreach (DataRow candidateDataRow in dataRow.GetChildRows(relationName))
			{
				DataRow languageDataRow = candidateDataRow.GetParentRow(relationName__Language);

				if (this.Current__Language == (BabebiDataSet.LanguageRow)languageDataRow)
				{
					return candidateDataRow;
				}
			}

			return null;
		}

		/// je ne sais pas pourquoi cette fonction doit avoir un effet "nullifiant" ?
		public void GetWordOrPatternPackage
		(
			string subscriberCodeOrNull,
			int? wordOrPatternIdOrNull,
		out string uniqueKeyString,
		out string meaning,
		ref BabebiDataSet.WordOrPatternRow wordOrPattern,
		ref BabebiDataSet.PatternRow pattern,
		ref BabebiDataSet.Pattern_LanguageRow pattern_Language,
		ref BabebiDataSet.WordRow word,
		ref BabebiDataSet.Word_LanguageRow word_Language,
			bool jump__Word__or__Pattern__finding = false,
			bool jump__Word_Language__or__Pattern_Language__finding = false,
			bool jump__WordOrPattern__finding = false
		)
		{
			if (subscriberCodeOrNull == null)
			{
				if (!jump__Word__or__Pattern__finding)
				{
					pattern = null;
					word = null;
				}

				if (!jump__Word_Language__or__Pattern_Language__finding)
				{
					pattern_Language = null;
					word_Language = null;
				}

				if (!jump__WordOrPattern__finding)
				{
					wordOrPattern = null;
				}

				uniqueKeyString = null;
				meaning = null;
			}
			else
			{
				if (subscriberCodeOrNull == MainForm.SubscriberCode_Pattern)
				{
					word = null;
					word_Language = null;

					if (!jump__Word_Language__or__Pattern_Language__finding)
					{
						pattern_Language
							= this.DataSet.Pattern_Language
							.FindByPatternIdLanguageCode
							(
								wordOrPatternIdOrNull.Value,
								this.Current__Language.Code
							);
					}

					if (!jump__Word__or__Pattern__finding)
					{
						pattern = pattern_Language.PatternRow;      /// this.DataSet.Pattern.FindById(wordOrPatternIdOrNull.Value);
					}

					uniqueKeyString = pattern.UniqueKeyString;
					meaning = pattern_Language.Meaning;

					if (!jump__WordOrPattern__finding)
					{
						wordOrPattern = pattern.WordOrPatternRowParent;
					}
				}
				else if (subscriberCodeOrNull == MainForm.SubscriberCode_Word)
				{
					pattern = null;
					pattern_Language = null;

					if (!jump__Word_Language__or__Pattern_Language__finding)
					{
						word_Language
							= this.DataSet.Word_Language
							.FindByWordIdLanguageCode
							(
								wordOrPatternIdOrNull.Value,
								this.Current__Language.Code
							);
					}

					if (!jump__Word__or__Pattern__finding)
					{
						word = word_Language.WordRowParent;     /// this.DataSet.Word.FindById(wordOrPatternIdOrNull.Value);
					}

					uniqueKeyString = word.UniqueKeyString;
					meaning = word_Language.Meaning;

					if (!jump__WordOrPattern__finding)
					{
						wordOrPattern = word.WordOrPatternRowParent;
					}
				}
				else
				{
					throw new NotImplementedException();
				}
			}
		}

		#region		fonctions de conversion 'ComboBoxSelectedItem <=> value'

		public static string	Convert__ComboBoxSelectedItem__into__Code__WordOrPattern(string comboTypeSelectedItem)
		{
			switch (comboTypeSelectedItem)
			{
				case MainForm.SubscriberName_Pattern:	return MainForm.SubscriberCode_Pattern;
				case MainForm.SubscriberName_Word:		return MainForm.SubscriberCode_Word;
				case MainForm.SubscriberName_None:		return null;
				default: throw new Exception();
			}
		}
		public static string	Convert__Code__into__ComboBoxSelectedItem__WordOrPattern(string subscriberCode)
		{
			switch (subscriberCode)
			{
				case MainForm.SubscriberCode_Pattern: return MainForm.SubscriberName_Pattern;
				case MainForm.SubscriberCode_Word: return MainForm.SubscriberName_Word;
				case null: return MainForm.SubscriberName_None;
				default: throw new Exception();
			}
		}

		public static short		Convert__ComboBoxSelectedItem__into__InsertionIndex(string insertionIndexComboBoxSelectedItem)
		{
			switch (insertionIndexComboBoxSelectedItem)
			{
				case "(undefined)": return -1;
				case "At the end": return 32;
				case "At the beginning": return 0;
				case "2nd position": return 1; ;
				case "3rd position": return 2;
				default:
				{
					string insertionIndexString
						= insertionIndexComboBoxSelectedItem
						.Remove
						(
							insertionIndexComboBoxSelectedItem.Length - 11
						);

					try
					{
						return short.Parse(insertionIndexString);
					}
					catch
					{
						throw new Exception();
					}
				}
			}
		}
		public static string	Convert__InsertionIndex__into__ComboBoxSelectedItem(short insertionIndex)
		{
			switch (insertionIndex)
			{
				case -1: return "(undefined)";
				case 32: return "At the end";
				case 0: return "At the beginning";
				case 1: return "2nd position"; ;
				case 2: return "3rd position";
				default:
				{
					return (insertionIndex + 1).ToString() + "th position";
				}
			}
		}

		#endregion	fonctions de conversion 'ComboBoxSelectedItem <=> value'

		#region		babebi-letter ordering

		private void		getSortedListKeyedByLetterList__RECURSIVE(Dictionary<string, object> tree, ref List<int> listOfObjectIds)
		{
			string[] unsortedListOfLetters = tree.Keys.ToArray();

			string[] sortedListOfLetters;

			string firstLetter = unsortedListOfLetters[0];

			if (this.isVowel(firstLetter))
			{
				sortedListOfLetters = this.getReorderedVowels(unsortedListOfLetters);
			}
			else if (this.isConsonant(firstLetter))
			{
				sortedListOfLetters = this.getReorderedConsonants(unsortedListOfLetters);
			}
			else
			{
				throw new Exception(firstLetter);
			}

			foreach (string letter in sortedListOfLetters)
			{
				if (tree[letter] is int objectId)
				{
					listOfObjectIds.Add(objectId);
				}
				else if (tree[letter] is Dictionary< string, object> subTree)
				{
					unsortedListOfLetters = subTree.Keys.ToArray<string>();

					this.getSortedListKeyedByLetterList__RECURSIVE(subTree, ref listOfObjectIds);
				}
				else
				{
					throw new Exception(letter);
				}
			}
		}
		private List<int>	getSortedListKeyedByLetterList(Dictionary<List<string>, int> letterLists__objectIds)
		{
			List<int> objectIdList = new List<int>();

			Dictionary<string, object> tree = new Dictionary<string, object>();

			int letterListCount = -1;
			List<bool> trueForVowels__falseForConsonants = new List<bool>();

			foreach (KeyValuePair<List<string>, int> keyValuePair in letterLists__objectIds)
			{
				List<string> letterList = keyValuePair.Key;
				int objectId = keyValuePair.Value;

				/// initialisation de letterListCount
				if (letterListCount == -1)
				{
					letterListCount = letterList.Count;
				}

				Dictionary<string, object> parentTree_ = tree;
				for (int j = 0; j < letterListCount; j++)
				{
					string letter = letterList[j];

					#region		initialisation de trueForVowels__falseForConsonants, if not done yet.

					if (trueForVowels__falseForConsonants.Count <= j)
					{
						if (this.isVowel(letter))
						{
							trueForVowels__falseForConsonants.Add(true);
						}
						else if (this.isConsonant(letter))
						{
							trueForVowels__falseForConsonants.Add(false);
						}
						else
						{
							throw new Exception(letter);
						}
					}

					#endregion	initialisation de trueForVowels__falseForConsonants, if not done yet.
					#region		verification si mélange de consonnes et de voyelles.

					bool registered__trueForVowel__falseForConsonant = trueForVowels__falseForConsonants[j];

					bool current__trueForVowel__falseForConsonant;
					if (this.isVowel(letter))
					{
						current__trueForVowel__falseForConsonant = true;
					}
					else if (this.isConsonant(letter))
					{
						current__trueForVowel__falseForConsonant = false;
					}
					else
					{
						throw new Exception(letter);
					}

					if
					(
						current__trueForVowel__falseForConsonant && !registered__trueForVowel__falseForConsonant
						||
						!current__trueForVowel__falseForConsonant && registered__trueForVowel__falseForConsonant
					)
					{
						throw new Exception(letter);
					}

					#endregion	verification si mélange de consonnes et de voyelles.

					if (j == letterListCount - 1)
					{
						parentTree_.Add(letter, objectId);
					}
					else
					{
						Dictionary<string, object> currentTree_;

						if (parentTree_.ContainsKey(letter))
						{
							currentTree_ = (Dictionary<string, object>)(parentTree_[letter]);
						}
						else
						{
							currentTree_ = new Dictionary<string, object>();

							parentTree_.Add(letter, currentTree_);
						}
					
						parentTree_ = currentTree_;
					}
				}
			}
			string[] unsortedListOfLetters = tree.Keys.ToArray<string>();

			this.getSortedListKeyedByLetterList__RECURSIVE(	tree, ref	objectIdList);

			string[] sortedListOfLetters;
			if (this.isVowel(unsortedListOfLetters[0]))
			{
				sortedListOfLetters = this.getReorderedVowels(unsortedListOfLetters);
			}
			else if (this.isConsonant(unsortedListOfLetters[0]))
			{
				sortedListOfLetters = this.getReorderedConsonants(unsortedListOfLetters);
			}
			else
			{
				throw new Exception(unsortedListOfLetters[0]);
			}

			foreach (string letter in sortedListOfLetters)
			{
				if (tree[letter] is int theObjectId)
				{
					objectIdList.Add(theObjectId);
				}
				else if (tree[letter] is Dictionary< string, object> theTree_)
				{
					unsortedListOfLetters = theTree_.Keys.ToArray<string>();
				}
				else
				{
					throw new Exception(letter);
				}
			}

			return objectIdList;
		}

		private bool		isVowel(string letterString)
		{
			foreach (string vowelString in this.VowelStrings)
			{
				if (vowelString == letterString)
				{ 
					return true;
				}
			}
			return false;
		}
		private string[]	getReorderedVowels(string[] providedVowelStrings)
		{ 
			string[] reorderedVowelStrings = new string[providedVowelStrings.Length];


			int i = -1;
			foreach(string vowelString in this.VowelStrings)
			{
				bool found = false;
				foreach (string providedVowelString in providedVowelStrings)
				{
					if (providedVowelString == vowelString)
					{
						found = true;

						break;
					}
				}
				if (found)
				{
					i++;

					reorderedVowelStrings[i] = vowelString;
				}
			}

			if (i != providedVowelStrings.Length - 1)
			{
				throw new Exception();
			}
			
			return reorderedVowelStrings;
		}

		private bool		isConsonant(string letterString)
		{
			foreach (string consonantString in this.ConsonantStrings)
			{
				if (consonantString == letterString)
				{ 
					return true;
				}
			}
			return false;
		}
		private string[]	getReorderedConsonants(string[] providedConsonantStrings)
		{ 
			string[] reorderedConsonantStrings = new string[providedConsonantStrings.Length];

			int i = -1;
			foreach(string consonantString in this.ConsonantStrings)
			{
				bool found = false;
				foreach (string providedConsonantString in providedConsonantStrings)
				{
					if (providedConsonantString == consonantString)
					{
						found = true;

						break;
					}
				}
				if (found)
				{
					i++;

					reorderedConsonantStrings[i] = consonantString;
				}
			}

			if (i != providedConsonantStrings.Length - 1)
			{
				throw new Exception();
			}
			
			return reorderedConsonantStrings;
		}

		#endregion	babebi-letter ordering


		/// afin de ne saisir que des chiffres.
		internal static void Integer__KeyPress(KeyPressEventArgs e)
		{
			char c = e.KeyChar;

			/// les chiffres + back + coller.
			if (char.IsNumber(c) || c == '\b' || c == '\u0016')	
			{
				e.Handled = false;
			}
			else
			{ 
				e.Handled = true;
			}
		}

		internal static void Searching__UniqueKeyString__KeyPress(bool preventCharEntry, KeyPressEventArgs e)
		{
			char c = e.KeyChar;

			/// back : toujours.
			if (c == '\b')	
			{
				e.Handled = false;
			}
			else
			{
				if (preventCharEntry)
				{
					e.Handled = true;
				}
				else
				{
					e.Handled = false;
				}
			}
		}

		/// some colors !
		internal static void Error__Configure_TextBox	(Label label, TextBox	textBox,	bool hasError, string blackValueString)
		{
			if (hasError)
			{
				label.ForeColor = Color.Red;
				textBox.ForeColor = Color.Red;
			}
			else
			{
				if (blackValueString == null || textBox.Text == blackValueString)
				{
					label.ForeColor = Color.Black;
					textBox.BackColor = Color.White;
					textBox.ForeColor = Color.Black;
				}
				else
				{ 
					label.ForeColor = Color.Blue;
					textBox.BackColor = Color.White;
					textBox.ForeColor = Color.Blue;
				}
			}
			
		}
		internal static void Error__Configure_ComboBox	(Label label, ComboBox	comboBox,	bool hasError, string blackValueString)
		{
			if (hasError)
			{
				label.ForeColor = Color.Red;
				comboBox.ForeColor = Color.Red;
			}
			else
			{
				if (blackValueString == null || (string)(comboBox.SelectedItem) == blackValueString)
				{
					label.ForeColor = Color.Black;
					comboBox.BackColor = Color.White;
					comboBox.ForeColor = Color.Black;
				}
				else
				{ 
					label.ForeColor = Color.Blue;
					comboBox.BackColor = Color.White;
					comboBox.ForeColor = Color.Blue;
				}
			}
			
		}


		/// <summary>
		/// return false if a character is not a valid babebi Letter.
		/// </summary>
		internal string Split_a_string_into_Letters(string aString, List<BabebiDataSet.LetterRow> letterRowList)
		{
			for (int i = 0; i < aString.Length; i++)
			{
				char firstChar = aString[i];

				if (i < aString.Length - 1)
				{
					char secondChar = aString[i + 1];

					string doubleCharLetterOrSymbol = new string(new char[] { firstChar, secondChar });

					BabebiDataSet.LetterRow doubleCharLetterRow
						= this.DataSet.Letter.FindByString(doubleCharLetterOrSymbol);

					if (doubleCharLetterRow != null)
					{
						letterRowList.Add(doubleCharLetterRow);

						i++;

						continue;
					}
				}

				string monoCharLetter = new string(new char[] { firstChar });

				BabebiDataSet.LetterRow monoCharLetterRow
					= this.DataSet.Letter.FindByString(monoCharLetter);

				if (monoCharLetterRow == null)
				{
					return monoCharLetter;
				}

				letterRowList.Add(monoCharLetterRow);
			}

			return null;
		}

		/// <summary>
		/// return false if a character is not a valid babebi Letter or Symbol.
		/// </summary>
		internal string Split_a_string_into_LetterOrSymbols(string aString, List<BabebiDataSet.LetterOrSymbolRow> letterOrSymbolList)
		{
			for (int i = 0; i < aString.Length; i++)
			{
				char firstChar = aString[i];

				string monoCharLetter = new string(new char[] { firstChar });

				if (monoCharLetter == this.TheSymbolForVowel.String)
				{
					letterOrSymbolList.Add(this.TheSymbolForVowel.LetterOrSymbolRowParent);
				}
				else if (monoCharLetter == this.TheSymbolForConsonant.String)
				{
					letterOrSymbolList.Add(this.TheSymbolForConsonant.LetterOrSymbolRowParent);
				}
				else
				{
					if (i < aString.Length - 1)
					{
						char secondChar = aString[i + 1];

						string doubleCharLetterOrSymbol = new string(new char[] { firstChar, secondChar });

						BabebiDataSet.LetterRow doubleCharLetterRow
							= this.DataSet.Letter.FindByString(doubleCharLetterOrSymbol);

						if (doubleCharLetterRow != null)
						{
							letterOrSymbolList.Add(doubleCharLetterRow.LetterOrSymbolRowParent);

							i++;

							continue;
						}
					}

					BabebiDataSet.LetterRow monoCharLetterRow
						= this.DataSet.Letter.FindByString(monoCharLetter);

					if (monoCharLetterRow == null)
					{
						return monoCharLetter;
					}

					letterOrSymbolList.Add(monoCharLetterRow.LetterOrSymbolRowParent);
				}
			}

			return null;
		}


		#endregion	Toolbox (static functions)

		internal delegate void FunctionReturningVoidWithNoArgument();
	}
}
