Example #1
0
	   // public event EventHandler<string> Merged;

		public FlexImporter(FdoCache cache)
		{
			_cache = cache;
			_flexMorphTypes = new MoMorphTypeCollection(_cache);
		}
Example #2
0
		public void MergeEntryAllomorphs()
		{
			CheckDisposed();

			ILexDb ldb = Cache.LangProject.LexDbOA;
			MoMorphTypeCollection mtCol = new MoMorphTypeCollection(Cache);
			string form = "cat";
			int clsid;
			IMoMorphType stemMT = MoMorphType.FindMorphType(Cache, mtCol, ref form, out clsid);
			form = "s-";
			IMoMorphType pfxMT = MoMorphType.FindMorphType(Cache, mtCol, ref form, out clsid);
			FdoOwningCollection<ILexEntry> entriesCol = ldb.EntriesOC;
			ILexEntry lmeKeeper = entriesCol.Add(new LexEntry());
			ILexEntry lmeSrc = entriesCol.Add(new LexEntry());

			try
			{
				// Set up stem allomorphs.
				MoStemAllomorph stemKeeper = (MoStemAllomorph)lmeKeeper.AlternateFormsOS.Append(new MoStemAllomorph());
				stemKeeper.MorphTypeRA = stemMT;
				stemKeeper.Form.VernacularDefaultWritingSystem = "cat";
				MoStemAllomorph stemToss = (MoStemAllomorph)lmeSrc.AlternateFormsOS.Append(new MoStemAllomorph());
				stemToss.MorphTypeRA = stemMT;
				stemToss.Form.VernacularDefaultWritingSystem = "cat";
				MoStemAllomorph stemKeep = (MoStemAllomorph)lmeSrc.AlternateFormsOS.Append(new MoStemAllomorph());
				stemKeep.MorphTypeRA = stemMT;
				stemKeep.Form.VernacularDefaultWritingSystem = "meow";

				// Set up affix allomorphs.
				MoAffixAllomorph daKeeper = (MoAffixAllomorph)lmeKeeper.AlternateFormsOS.Append(new MoAffixAllomorph());
				daKeeper.MorphTypeRA = pfxMT;
				daKeeper.Form.VernacularDefaultWritingSystem = "s";
				MoAffixAllomorph daToss = (MoAffixAllomorph)lmeSrc.AlternateFormsOS.Append(new MoAffixAllomorph());
				daToss.MorphTypeRA = pfxMT;
				daToss.Form.VernacularDefaultWritingSystem = "s";

				// Merge entries.
				lmeKeeper.MergeObject(lmeSrc);
				Assert.AreEqual(3, lmeKeeper.AlternateFormsOS.Count);
			}
			finally
			{
				entriesCol.Remove(lmeKeeper);
			}
		}
Example #3
0
		/// <summary>
		/// Checks two morph types objects to see if they are ambiguous,
		/// regarding the markers used to type them.
		/// </summary>
		/// <param name="cache">FDO cache.</param>
		/// <param name="types">Collection of morph types.</param>
		/// <param name="first">First morph type to compare</param>
		/// <param name="second">Second morph type to compare</param>
		/// <returns>True, if the two morph types are ambiguous, otherwise false.</returns>
		public bool IsAmbiguousWith(FdoCache cache, MoMorphTypeCollection types,
			IMoMorphType first, IMoMorphType second)
		{
			// Debug.Assert(types != null); JohnT removed assert as argument is not used and new caller does not provide
			Debug.Assert(first != null);
			Debug.Assert(second != null);
			int idxFirst = FindMorphTypeIndex(cache, first);
			int idxSecond = FindMorphTypeIndex(cache, second);
			bool areAmbiguous = false;

			switch (idxFirst)
			{
				case kmtCircumfix:
				case kmtRoot:
				case kmtProclitic:
				case kmtClitic:
				case kmtParticle:
				case kmtEnclitic:
				case kmtStem:
				case kmtPhrase:
				case kmtDiscontiguousPhrase:
					if (idxSecond != idxFirst)
						areAmbiguous = (idxSecond == kmtCircumfix)
							|| (idxSecond == kmtRoot)
							|| (idxSecond == kmtClitic)
							|| (idxSecond == kmtProclitic)
							|| (idxSecond == kmtParticle)
							|| (idxSecond == kmtEnclitic)
							|| (idxSecond == kmtStem)
							|| (idxSecond == kmtPhrase)
							|| (idxSecond == kmtDiscontiguousPhrase);
					break;
				case kmtBoundStem:
					areAmbiguous = (idxSecond == kmtBoundRoot);
					break;
				case kmtBoundRoot:
					areAmbiguous = (idxSecond == kmtBoundStem);
					break;
				case kmtInfix:
					areAmbiguous = (idxSecond == kmtInfixingInterfix);
					break;
				case kmtInfixingInterfix:
					areAmbiguous = (idxSecond == kmtInfix);
					break;
				case kmtPrefix:
					areAmbiguous = (idxSecond == kmtPrefixingInterfix);
					break;
				case kmtPrefixingInterfix:
					areAmbiguous = (idxSecond == kmtPrefix);
					break;
				case kmtSuffix:
					areAmbiguous = (idxSecond == kmtSuffixingInterfix);
					break;
				case kmtSuffixingInterfix:
					areAmbiguous = (idxSecond == kmtSuffix);
					break;
				default:
					break;
			}

			return areAmbiguous;
		}
Example #4
0
		/// <summary>
		/// Get the morph type and class ID for the given input string.
		/// </summary>
		/// <param name="cache">The cache to look in.</param>
		/// <param name="types">Collection of all of the MoMorphType objects.</param>
		/// <param name="fullForm">The MoForm form, plus optional key characters before and/or after the form.</param>
		/// <param name="clsidForm">Return the clsid for the form.</param>
		/// <returns>The MoMorphType indicated by the possible markers.</returns>
		/// <exception cref="ArgumentException">
		/// Thrown in the following cases:
		/// 1. The input form is an empty string,
		/// 2. The imput form is improperly marked according to the current settings of the
		///		MoMorphType objects.
		/// </exception>
		public static IMoMorphType FindMorphType(FdoCache cache, MoMorphTypeCollection types,
			ref string fullForm, out int clsidForm)
		{
			Debug.Assert(cache != null);
			Debug.Assert(fullForm != null);

			clsidForm = MoStemAllomorph.kclsidMoStemAllomorph;	// default
			IMoMorphType mt = null;
			fullForm = fullForm.Trim();
			if (fullForm.Length == 0)
				throw new ArgumentException("The form is empty.", "fullForm");

			string sLeading;
			string sTrailing;
			GetAffixMarkers(cache, fullForm, out sLeading, out sTrailing);

			/*
			 Not dealt with.
			 particle	(ambiguous: particle, circumfix, root, stem)
			 circumfix	(ambiguous: particle, circumfix, root, stem)
			 root		(ambiguous: particle, circumfix, root, stem)
			 bound root	(ambiguous: bound root, bound stem)
			 infixing interfix	(ambiguous: infixing interfix, infix)
			 prefixing interfix	(ambiguous: prefixing interfix, prefix)
			 suffixing interfix	(ambiguous: suffixing interfix, suffix)
			 End of not dealt with.

			What we do deal with.
			 prefix-	(ambiguous: prefixing interfix, prefix)
			=simulfix=
			-suffix		(ambiguous: suffixing interfix, suffix)
			-infix-		(ambiguous: infixing interfix, infix)
			~suprafix~
			=enclitic
			 proclitic=
			*bound stem	(ambiguous: bound root, bound stem)
			 stem		(ambiguous: particle, circumfix, root, stem)
			End of what we do deal with.

			For ambiguous cases, pick 'root' and 'bound root', as per LarryH's suggestion on 11/18/2003.
			(Changed: May, 2004). For ambiguous cases, pick 'stem' and 'bound stem',
			as per WordWorks May, 2004 meeting (Andy Black & John Hatton).
			For ambiguous cases, pick 'infix', 'prefix', and 'suffix'.
			 */
			if (sLeading == types.Item(kmtStem).Prefix && sTrailing == types.Item(kmtStem).Postfix)
			{
				mt = types.Item(kmtStem);	// may be ambiguous with particle, root, and circumfix
			}
			else if (sLeading == types.Item(kmtPrefix).Prefix && sTrailing == types.Item(kmtPrefix).Postfix)
			{
				mt = types.Item(kmtPrefix); // may be ambiguous with prefixing interfix
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtInfix).Prefix && sTrailing == types.Item(kmtInfix).Postfix)
			{
				mt = types.Item(kmtInfix);	// may be ambiguous with infixing interfix
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtSuffix).Prefix && sTrailing == types.Item(kmtSuffix).Postfix)
			{
				mt = types.Item(kmtSuffix);	// may be ambiguous with suffixing interfix
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtBoundStem).Prefix && sTrailing == types.Item(kmtBoundStem).Postfix)
			{
				mt = types.Item(kmtBoundStem);	// may be ambiguous with bound root
			}
			else if (sLeading == types.Item(kmtProclitic).Prefix && sTrailing == types.Item(kmtProclitic).Postfix)
			{
				mt = types.Item(kmtProclitic);
			}
			else if (sLeading == types.Item(kmtEnclitic).Prefix && sTrailing == types.Item(kmtEnclitic).Postfix)
			{
				mt = types.Item(kmtEnclitic);
			}
			else if (sLeading == types.Item(kmtSimulfix).Prefix && sTrailing == types.Item(kmtSimulfix).Postfix)
			{
				mt = types.Item(kmtSimulfix);
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtSuprafix).Prefix && sTrailing == types.Item(kmtSuprafix).Postfix)
			{
				mt = types.Item(kmtSuprafix);
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtBoundRoot).Prefix && sTrailing == types.Item(kmtBoundRoot).Postfix)
			{
				mt = types.Item(kmtBoundRoot);
			}
			else if (sLeading == types.Item(kmtRoot).Prefix && sTrailing == types.Item(kmtRoot).Postfix)
			{
				mt = types.Item(kmtRoot);
			}
			else if (sLeading == types.Item(kmtParticle).Prefix && sTrailing == types.Item(kmtParticle).Postfix)
			{
				mt = types.Item(kmtParticle);
			}
			else if (sLeading == types.Item(kmtCircumfix).Prefix && sTrailing == types.Item(kmtCircumfix).Postfix)
			{
				mt = types.Item(kmtCircumfix);
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtPrefixingInterfix).Prefix && sTrailing == types.Item(kmtPrefixingInterfix).Postfix)
			{
				mt = types.Item(kmtPrefixingInterfix);
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtInfixingInterfix).Prefix && sTrailing == types.Item(kmtInfixingInterfix).Postfix)
			{
				mt = types.Item(kmtInfixingInterfix);
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtSuffixingInterfix).Prefix && sTrailing == types.Item(kmtSuffixingInterfix).Postfix)
			{
				mt = types.Item(kmtSuffixingInterfix);
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else
			{
				if (sLeading == null && sTrailing == null)
					throw new Exception(String.Format(Strings.ksInvalidUnmarkedForm0, fullForm));
				else if (sLeading == null)
					throw new Exception(String.Format(Strings.ksInvalidForm0Trailing1, fullForm, sTrailing));
				else if (sTrailing == null)
					throw new Exception(String.Format(Strings.ksInvalidForm0Leading1, fullForm, sLeading));
				else
					throw new Exception(String.Format(Strings.ksInvalidForm0Leading1Trailing2, fullForm, sLeading, sTrailing));
			}

			if (sLeading != null)
				fullForm = fullForm.Substring(sLeading.Length);
			if (sTrailing != null)
				fullForm = fullForm.Substring(0, fullForm.Length - sTrailing.Length);

			// Handle prhase
			if (mt.Guid.ToString().ToLower() == MoMorphType.kguidMorphStem)
			{
				if (fullForm.IndexOf(" ") != -1)
					mt = types.Item(kmtPhrase);
			}

			// Check to see if it has any of the reserved characters remaining,
			// as we have now stripped them off the ends,
			// and it is illegal to have them internal to the form.
			// (SteveMc) But is it? What about hyphenated words? Or contractions?
			// if ((MiscUtils.IndexOfAnyString(fullForm, prefixMarkers, 0, out iMatchedPrefix) > -1) ||
			// 	(MiscUtils.IndexOfAnyString(fullForm, postfixMarkers, 0, out iMatchedPrefix) > -1))
			// {
			// 	throw new Exception("\"" + fullForm + "\" is not a valid morpheme. It should not have a reserved morpheme marker within the form. Did you forget spaces?");
			// }

			return mt;
		}
Example #5
0
		/// <summary>
		/// Confirm that we can break the specified string into the two parts needed for a circumfix.
		/// Return true (and the two parts, not stripped of affix markers) if successful.
		/// </summary>
		static public bool GetCircumfixLeftAndRightParts(FdoCache cache, ITsString tssLexemeForm,
			out string sLeftMember, out string sRightMember)
		{
			// split citation form into left and right parts
			sLeftMember = null;
			sRightMember = null;
			char[] aSpacePeriod = new char[2] { ' ', '.' };
			string lexemeForm = tssLexemeForm.Text;
			int wsVern = StringUtils.GetWsAtOffset(tssLexemeForm, 0);
			int iLeftEnd = lexemeForm.IndexOfAny(aSpacePeriod);
			if (iLeftEnd < 0)
				return false;
			else
				sLeftMember = lexemeForm.Substring(0, iLeftEnd);
			int iRightBegin = lexemeForm.LastIndexOfAny(aSpacePeriod);
			if (iRightBegin < 0)
				return false;
			else
				sRightMember = lexemeForm.Substring(iRightBegin + 1);
			MoMorphTypeCollection mmtCol = new MoMorphTypeCollection(cache);
			int clsidForm;
			try
			{
				string temp = sLeftMember;
				MoMorphType.FindMorphType(cache, mmtCol, ref temp, out clsidForm);
				temp = sRightMember;
				MoMorphType.FindMorphType(cache, mmtCol, ref temp, out clsidForm);
			}
			catch(Exception)
			{
				return false;
			}
			return true;
		}
Example #6
0
			int m_cchPrevMorphemes; // Total length of morphemes before m_imorph.

			public MorphemeBreaker(CachePair caches, string input, int hvoSbWord, int wsVern,
				SandboxBase sandbox)
			{
				m_caches = caches;
				m_sda = caches.DataAccess;
				m_cda = (IVwCacheDa)m_sda;
				m_input = input;
				m_hvoSbWord = hvoSbWord;
				m_cOldMorphs = m_sda.get_VecSize(m_hvoSbWord, ktagSbWordMorphs);
				ITsStrFactory m_tsf = TsStrFactoryClass.Create();
				m_wsVern = wsVern;
				m_types = new MoMorphTypeCollection(m_caches.MainCache);
				m_sandbox = sandbox;
			}
Example #7
0
		/// <summary>
		/// Initialize an InsertEntryDlg from something like an "Insert Major Entry menu".
		/// </summary>
		/// <param name="cache">The FDO cache to use.</param>
		protected void SetDlgInfo(FdoCache cache)
		{
			if (m_types == null)
				m_types = new MoMorphTypeCollection(cache);
			SetDlgInfo(cache, m_types.Item(MoMorphType.kmtStem));
		}
Example #8
0
		/// <summary>
		/// Collect all the homographs of the given form from the given list of entries.  If fMatchLexForms
		/// is true, then match against lexeme forms even if citation forms exist.  (This behavior is needed
		/// to fix LT-6024 for categorized entry.)
		/// </summary>
		/// <param name="sForm"></param>
		/// <param name="hvo"></param>
		/// <param name="entries"></param>
		/// <param name="nMorphType"></param>
		/// <param name="fMatchLexForms"></param>
		/// <returns></returns>
		internal static List<ILexEntry> CollectHomographs(string sForm, int hvo, List<ILexEntry> entries,
			int nMorphType, bool fMatchLexForms)
		{
			if (sForm == null || sForm == String.Empty || sForm == Strings.ksQuestions)		// was "??", not "???"
				return new List<ILexEntry>(0);
			if (entries.Count == 0)
				return new List<ILexEntry>(0);

			MoMorphTypeCollection typesCol = null;
			List<ILexEntry> rgHomographs = new List<ILexEntry>();
			// Treat stems and roots as equivalent, bound or unbound, as well as entries with no
			// idea what they are.
			if (nMorphType == MoMorphType.kmtBoundRoot ||
				nMorphType == MoMorphType.kmtBoundStem ||
				nMorphType == MoMorphType.kmtUnknown ||
				nMorphType == MoMorphType.kmtRoot ||
				nMorphType == MoMorphType.kmtParticle ||
				nMorphType == MoMorphType.kmtPhrase ||
				nMorphType == MoMorphType.kmtDiscontiguousPhrase)
			{
				nMorphType = MoMorphType.kmtStem;
			}

			FdoCache cache = entries[0].Cache;
			Debug.Assert(cache != null);
			try
			{
				cache.EnableBulkLoadingIfPossible(true);
				foreach (ILexEntry le in entries)
				{
					string homographForm = le.HomographForm;
					string lexemeHomograph = homographForm;
					if (fMatchLexForms)
						lexemeHomograph = LexemeFormStatic(le.Cache, le.Hvo);
					Debug.Assert(le != null);
					if (typesCol == null)
						typesCol = new MoMorphTypeCollection(cache);
					if (le.Hvo != hvo && (homographForm == sForm || lexemeHomograph == sForm))
					{
						List<IMoMorphType> types = le.MorphTypes;
						foreach (IMoMorphType mmt in types)
						{
							int nType = MoMorphType.FindMorphTypeIndex(cache, mmt);
							if (nType == MoMorphType.kmtBoundRoot ||
								nType == MoMorphType.kmtBoundStem ||
								nType == MoMorphType.kmtUnknown ||
								nType == MoMorphType.kmtRoot ||
								nType == MoMorphType.kmtParticle ||
								nType == MoMorphType.kmtPhrase ||
								nType == MoMorphType.kmtDiscontiguousPhrase)
							{
								nType = MoMorphType.kmtStem;
							}
							if (nType == nMorphType)
							{
								rgHomographs.Add(le);
								// Only add it once, even if it has multiple morph type matches.
								break;
							}
						}
						// Go ahead and use it, since it has no types at all, as may be the case
						// for entries created by the Rapid Data Entry tool.
						if (types.Count == 0)
							rgHomographs.Add(le);
					}
				}
			}
			finally
			{
				cache.EnableBulkLoadingIfPossible(false);
			}
			return rgHomographs;
		}
Example #9
0
		protected void SetDlgInfo(FdoCache cache, IMoMorphType morphType, int wsVern, MorphTypeFilterType filter)
		{
			ReplaceMatchingEntriesControl();
			IVwStylesheet stylesheet = null;
			if (m_mediator != null)
			{
				stylesheet = FontHeightAdjuster.StyleSheetFromMediator(m_mediator);
				if (matchingEntries != null)
					matchingEntries.Initialize(cache, stylesheet, m_mediator);
			}
			m_cache = cache;

			m_fNewlyCreated = false;
			m_oldForm = "";

			if (m_types == null)
				m_types = new MoMorphTypeCollection(cache);

			// Set fonts for the two edit boxes.
			if (stylesheet != null)
			{
				tbLexicalForm.StyleSheet = stylesheet;
				tbGloss.StyleSheet = stylesheet;
			}

			// Set writing system factory and code for the two edit boxes.
			tbLexicalForm.WritingSystemFactory = cache.LanguageWritingSystemFactoryAccessor;
			if (wsVern <= 0)
				wsVern = cache.LangProject.DefaultVernacularWritingSystem;
			tbLexicalForm.WritingSystemCode = wsVern;
			tbLexicalForm.AdjustStringHeight = false;

			tbGloss.WritingSystemFactory = cache.LanguageWritingSystemFactoryAccessor;
			tbGloss.WritingSystemCode = cache.LangProject.DefaultAnalysisWritingSystem;
			tbGloss.AdjustStringHeight = false;

			// initialize to empty TsStrings
			ITsStrFactory tsf = TsStrFactoryClass.Create();
			//we need to use the weVern so that tbLexicalForm is sized correctly for the font size.
			//In Interlinear text the baseline can be in any of the vernacular writing systems, not just
			//the defaultVernacularWritingSystem.
			TssForm = tsf.MakeString("", wsVern);
			TssGloss = tsf.MakeString("", cache.LangProject.DefaultAnalysisWritingSystem);
			((System.ComponentModel.ISupportInitialize)(this.tbLexicalForm)).EndInit();
			((System.ComponentModel.ISupportInitialize)(this.tbGloss)).EndInit();


			int cVern = LabeledMultiStringView.GetWritingSystemList(m_cache, LangProject.kwsVerns, false).Length;
			if (cVern > 1)
			{
				msLexicalForm = ReplaceTextBoxWithMultiStringBox(tbLexicalForm, LangProject.kwsVerns, stylesheet);
				msLexicalForm.TextChanged += new EventHandler(tbLexicalForm_TextChanged);
			}
			else
			{
				// See if we need to adjust the height of the lexical form
				AdjustTextBoxAndDialogHeight(tbLexicalForm);
			}

			// JohnT addition: if multiple analysis writing systems, replace tbGloss with msGloss
			int cWritingSystem = LabeledMultiStringView.GetWritingSystemList(m_cache, LangProject.kwsAnals, false).Length;
			if (cWritingSystem > 1)
			{
				msGloss = ReplaceTextBoxWithMultiStringBox(tbGloss, LangProject.kwsAnals, stylesheet);
				m_lnkAssistant.Top = msGloss.Bottom - m_lnkAssistant.Height;
				msGloss.TextChanged += new System.EventHandler(this.tbGloss_TextChanged);
			}
			else
			{
				// See if we need to adjust the height of the gloss
				AdjustTextBoxAndDialogHeight(tbGloss);
			}

			m_msaGroupBox.Initialize(cache, m_mediator, m_lnkAssistant, this);
			// See if we need to adjust the height of the MSA group box.
			int oldHeight = m_msaGroupBox.Height;
			int newHeight = Math.Max(m_msaGroupBox.PreferredHeight, oldHeight);
			GrowDialogAndAdjustControls(newHeight - oldHeight, m_msaGroupBox);
			m_msaGroupBox.AdjustInternalControlsAndGrow();

			Text = GetTitle();
			m_lnkAssistant.Enabled = false;

			// Set font for the combobox.
			cbMorphType.Font =
				new Font(cache.LangProject.DefaultAnalysisWritingSystemFont, 10);

			// Populate morph type combo.
			// first Fill ComplexFormType combo, since cbMorphType controls
			// whether it gets enabled and which index is selected.
			cbComplexFormType.Font =
				new Font(cache.LangProject.DefaultAnalysisWritingSystemFont, 10);
			List<ICmPossibility> rgComplexTypes = new List<ICmPossibility>(m_cache.LangProject.LexDbOA.ComplexEntryTypesOA.ReallyReallyAllPossibilities.ToArray());
			rgComplexTypes.Sort();
			m_idxNotComplex = cbComplexFormType.Items.Count;
			cbComplexFormType.Items.Add(new DummyEntryType(LexTextControls.ksNotApplicable, false));
			m_idxUnknownComplex = cbComplexFormType.Items.Count;
			cbComplexFormType.Items.Add(new DummyEntryType(LexTextControls.ksUnknownComplexForm, true));
			for (int i = 0; i < rgComplexTypes.Count; ++i)
			{
				ILexEntryType type = (ILexEntryType)rgComplexTypes[i];
				cbComplexFormType.Items.Add(type);
			}
			cbComplexFormType.SelectedIndex = 0;
			cbComplexFormType.Visible = true;
			cbComplexFormType.Enabled = true;
			// Convert from Set to List, since the Set can't sort.

			List<ICmPossibility> al = new List<ICmPossibility>();
			foreach (ICmPossibility mType in m_cache.LangProject.LexDbOA.MorphTypesOA.ReallyReallyAllPossibilities)
			{
				switch (filter)
				{
					case MorphTypeFilterType.prefix:
						if (MoMorphType.IsPrefixishType(m_cache, mType.Hvo))
							al.Add(mType);
						break;

					case MorphTypeFilterType.suffix:
						if (MoMorphType.IsSuffixishType(m_cache, mType.Hvo))
							al.Add(mType);
						break;

					case MorphTypeFilterType.any:
						al.Add(mType);
						break;
				}
			}
			al.Sort();
			for (int i = 0; i < al.Count; ++i)
			{
				IMoMorphType type = (IMoMorphType)al[i];

				cbMorphType.Items.Add(type);
				//previously had "if (type == morphType)" which was always false
				if (type.Equals(morphType))
					cbMorphType.SelectedIndex = i;
			}

			m_morphType = morphType; // Is this still needed?
			m_msaGroupBox.MorphTypePreference = m_morphType;
			// Now position the searching animation
			/*
			 * This position put the animation over the Glossing Assistant button. LT-9146
			m_searchAnimtation.Top = groupBox2.Top - m_searchAnimtation.Height - 5;
			m_searchAnimtation.Left = groupBox2.Right - m_searchAnimtation.Width - 10;
			 */
			/* This position puts the animation over the top left corner, but will that
			 * look okay with right-to-left?
			m_searchAnimtation.Top = groupBox2.Top + 40;
			m_searchAnimtation.Left = groupBox2.Left + 10;
			 */
			// This position puts the animation close to the middle of the list.
			m_searchAnimtation.Top = groupBox2.Top + (groupBox2.Top / 2);
			m_searchAnimtation.Left = groupBox2.Left + (groupBox2.Right / 2);
		}
Example #10
0
		/// <summary>
		/// Initialize an InsertEntryDlg from something like an "Insert Major Entry menu".
		/// </summary>
		/// <param name="cache">The FDO cache to use.</param>
		/// <param name="tssForm">The initial form to use.</param>
		/// <param name="mediator">The XCore.Mediator to use.</param>
		public void SetDlgInfo(FdoCache cache, ITsString tssForm, Mediator mediator)
		{
			CheckDisposed();

			m_mediator = mediator;
			if (m_types == null)
				m_types = new MoMorphTypeCollection(cache);
			string form = tssForm.Text;
			int clsidForm;
			IMoMorphType mmt;

			// Check whether the incoming form is vernacular or analysis.
			// (See LT-4074 and LT-7240.)
			int wsForm;
			bool fVern = IsFormWsInCurrentVernWs(cache, tssForm, out wsForm);
			// If form is empty (cf. LT-1621), use stem
			if (tssForm.Length == 0 || !fVern)
				mmt = m_types.Item(MoMorphType.kmtStem);
			else
				mmt = MoMorphType.FindMorphType(cache, m_types, ref form, out clsidForm);
			int wsVern = fVern ? wsForm : cache.DefaultVernWs;
			SetDlgInfo(cache, mmt, wsVern, MorphTypeFilterType.any);
			if (fVern)
			{
				TssForm = tssForm;
				TssGloss = cache.MakeAnalysisTss("");
				// The lexical form is already set, so shift focus to the gloss when
				// the form is activated.
				m_fLexicalFormInitialFocus = false;
			}
			else
			{
				TssForm = cache.MakeVernTss("");
				TssGloss = tssForm;
				// The gloss is already set, so shift the focus to the lexical form
				// when the form is activated.
				m_fLexicalFormInitialFocus = m_fLexicalFormChanged = true;
			}

			UpdateMatches();
		}
		private bool IsStemType(int hvo)
		{
			MoMorphTypeCollection types = new MoMorphTypeCollection(m_cache);
			if ((hvo == types.Item(MoMorphType.kmtBoundRoot).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtBoundStem).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtEnclitic).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtParticle).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtProclitic).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtRoot).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtStem).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtClitic).Hvo) ||
				// Andy: no! circumfixes are affixes, not stems: (hvo == types.Item(MoMorphType.kmtCircumfix).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtPhrase).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtDiscontiguousPhrase).Hvo) )
				return true;
			return false;
		}
Example #12
0
			public FlexConverter(FdoCache cache)
				: base()
			{
				m_cache = cache;
				m_rgmmt = new MoMorphTypeCollection(m_cache);
				m_wsEn = m_cache.LanguageWritingSystemFactoryAccessor.GetWsFromStr("en");
			}
Example #13
0
			private void GetMorphInfo(out ITsString tssForm, out ITsString tssFullForm, out int hvoMorphReal, out int hvoType)
			{
				int hvoMorph = m_caches.DataAccess.get_ObjectProp(m_hvoMorph, ktagSbMorphForm);
				hvoMorphReal = m_caches.RealHvo(hvoMorph);
				ISilDataAccess sda = m_caches.DataAccess;
				tssForm = m_caches.DataAccess.get_MultiStringAlt(hvoMorph, ktagSbNamedObjName, m_sandbox.RawWordformWs);
				tssFullForm = m_sandbox.GetFullMorphForm(m_hvoMorph);
				string fullForm = tssFullForm.Text;
				hvoType = 0;
				if (hvoMorphReal != 0)
				{
					hvoType = m_caches.MainCache.GetObjProperty(hvoMorphReal,
						(int)MoForm.MoFormTags.kflidMorphType);
				}
				else
				{
					// if we don't have a form then we can't derive a type. (cf. LT-1621)
					if (fullForm == null || fullForm == string.Empty)
					{
						hvoType = 0;
					}
					else
					{
						// Find the type for this morpheme
						int clsidForm;
						string fullFormTmp = fullForm;
						MoMorphTypeCollection morphtypes = new MoMorphTypeCollection(m_caches.MainCache);
						IMoMorphType mmt = MoMorphType.FindMorphType(m_caches.MainCache, morphtypes,
							ref fullFormTmp, out clsidForm);
						hvoType = mmt.Hvo;
					}
				}
			}
Example #14
0
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing)
		{
			//Debug.WriteLineIf(!disposing, "****************** " + GetType().Name + " 'disposing' is false. ******************");
			// Must not be run more than once.
			if (IsDisposed)
				return;

			if (disposing)
			{
				if (components != null)
				{
					components.Dispose();
				}
				if (matchingEntries != null)
				{
					if (matchingEntries is MatchingEntries)
					{
						(matchingEntries as MatchingEntries).SearchingChanged -= new EventHandler(matchingEntries_SearchingChanged);
						(matchingEntries as MatchingEntries).RestoreFocus -= new EventHandler(matchingEntries_RestoreFocus);
						(matchingEntries as MatchingEntries).SelectionChanged -= new SIL.FieldWorks.Common.Utils.FwSelectionChangedEventHandler(this.matchingEntries_SelectionChanged);
					}
					matchingEntries.Dispose();
				}

			}
			m_types = null;
			matchingEntries = null;
			m_startingEntry = null;

			base.Dispose(disposing);
		}
Example #15
0
		/// <summary>
		/// Gets a set of all hvos of all valid morph type references for this MoForm
		/// </summary>
		/// <returns>A set of hvos.</returns>
		public Set<int> GetAllMorphTypeReferenceTargetCandidates()
		{
			Set<int> set = new Set<int>(m_cache.LangProject.LexDbOA.MorphTypesOA.PossibilitiesOS.HvoArray);
			MoMorphTypeCollection types = new MoMorphTypeCollection(m_cache);
			if (OwningFlid == (int)LexEntry.LexEntryTags.kflidAlternateForms)
				set.Remove(types.Item(MoMorphType.kmtCircumfix).Hvo); // only for lexemeform
			return set;
		}
Example #16
0
		protected override void SetDlgInfo(FdoCache cache, WindowParams wp, Mediator mediator, int wsVern)
		{
			CheckDisposed();
			m_types = new MoMorphTypeCollection(cache);
			base.SetDlgInfo(cache, wp, mediator, wsVern);
		}
Example #17
0
		/// <summary>
		/// Get a set of hvos that are suitable for targets to a reference property.
		/// Subclasses should override this method to return a sensible list of IDs.
		/// </summary>
		/// <param name="flid">The reference property that can store the IDs.</param>
		/// <returns>A set of hvos.</returns>
		public override Set<int> ReferenceTargetCandidates(int flid)
		{
			Set<int> set = null;
			switch (flid)
			{
				case (int)MoForm.MoFormTags.kflidMorphType:
					set = new Set<int>(m_cache.LangProject.LexDbOA.MorphTypesOA.PossibilitiesOS.HvoArray);
					// Remove root and stem types.
					MoMorphTypeCollection types = new MoMorphTypeCollection(m_cache);
					set.Remove(types.Item(MoMorphType.kmtBoundRoot).Hvo);
					set.Remove(types.Item(MoMorphType.kmtBoundStem).Hvo);
					set.Remove(types.Item(MoMorphType.kmtClitic).Hvo);
					set.Remove(types.Item(MoMorphType.kmtEnclitic).Hvo);
					set.Remove(types.Item(MoMorphType.kmtParticle).Hvo);
					set.Remove(types.Item(MoMorphType.kmtProclitic).Hvo);
					set.Remove(types.Item(MoMorphType.kmtRoot).Hvo);
					set.Remove(types.Item(MoMorphType.kmtStem).Hvo);
					set.Remove(types.Item(MoMorphType.kmtPhrase).Hvo);
					set.Remove(types.Item(MoMorphType.kmtDiscontiguousPhrase).Hvo);
					if (OwningFlid == (int)LexEntry.LexEntryTags.kflidAlternateForms)
						set.Remove(types.Item(MoMorphType.kmtCircumfix).Hvo); // only for lexemeform
					break;
				case (int)MoAffixForm.MoAffixFormTags.kflidInflectionClasses:
					set = new Set<int>();
					//List<CmPossibility> poses = m_cache.LangProject.PartsOfSpeechOA.ReallyReallyAllPossibilities;
					int ownerID = OwnerHVO;
					int ownerClass = m_cache.GetIntProperty(ownerID, (int)CmObjectFields.kflidCmObject_Class);
					if (ownerClass == LexEntry.kclsidLexEntry)
					{
						ILexEntry entry = LexEntry.CreateFromDBObject(m_cache, ownerID);
						foreach (IMoMorphSynAnalysis msa in entry.MorphoSyntaxAnalysesOC)
						{
							if (msa is IMoInflAffMsa)
							{
								IMoInflAffMsa infafxmsa = (IMoInflAffMsa)msa;
								IPartOfSpeech pos = infafxmsa.PartOfSpeechRA;
								if (pos != null)
								{
									foreach (IMoInflClass ic in pos.AllInflectionClasses)
										set.Add(ic.Hvo);
								}
							}
							// Review: is this correct?  I think the TO POS is the relevant
							// one for derivational affixes, but maybe nothing is.
							// HAB says: From is the correct one to use for the allomorphs.  The From indicates
							// the category to which the affix attaches.  This category is the one that
							// may have the inflection classes, one or more of which this allomorph may go with.
							else if (msa is IMoDerivAffMsa)
							{
								IMoDerivAffMsa drvafxmsa = (IMoDerivAffMsa)msa;
								IPartOfSpeech pos = drvafxmsa.FromPartOfSpeechRA;
								if (pos != null)
								{
									foreach (IMoInflClass ic in pos.AllInflectionClasses)
										set.Add(ic.Hvo);
								}
							}
						}
					}
					break;
				default:
					set = base.ReferenceTargetCandidates(flid);
					break;
			}
			return set;
		}
Example #18
0
		/// <summary>
		/// This is invoked (using reflection) by an XmlRDEBrowseView when the user presses
		/// "Enter" in an RDE view that is displaying lexeme form and definition.
		/// (Maybe also on loss of focus, switch domain, etc?)
		/// It creates a new entry, lexeme form, and sense that are linked to the specified domain.
		/// Typically, later, a call to RDEMergeSense will be made to see whether this
		/// new entry should be merged into some existing sense.
		/// Note that this method is NOT responsible to insert the new sense into
		/// the fake property tagList of hvoDomain. (The caller will do that.)
		/// </summary>
		/// <param name="hvoDomain">database id of the semantic domain</param>
		/// <param name="tagList">id of the inverse relation for the senses that belong to the
		/// domain</param>
		/// <param name="columns"></param>
		/// <param name="rgtss"></param>
		/// <param name="cache"></param>
		/// <param name="stringTbl"></param>
		public static int RDENewSense(int hvoDomain, int tagList,
			List<XmlNode> columns, ITsString[] rgtss, FdoCache cache, StringTable stringTbl)
		{
			Debug.Assert(hvoDomain != 0);
			Debug.Assert(rgtss.Length == columns.Count);

			// Make a new sense in a new entry.
			ILexEntry le = cache.LangProject.LexDbOA.EntriesOC.Add(
				new LexEntry());
			IMoForm morph = null;

			// create a LexSense that has the given definition and semantic domain
			// Needs to be LexSense, since later calls use non-interface methods.
			LexSense ls = (LexSense)le.SensesOS.Append(new LexSense());

			ILgWritingSystemFactory wsf = cache.LanguageWritingSystemFactoryAccessor;
			// go through each column and store the appropriate information.
			for (int i = 0; i < columns.Count; ++i)
			{
				// Review: Currently we key off the column labels to determine which columns
				// correspond to CitationForm and which correspond to Definition.
				// Ideally we'd like to get at the flids used to build the column display strings.
				// Instead of passing in only ITsStrings, we could pass in a structure containing
				// an index of strings with any corresponding flids.  Here we'd expect strings
				// based upon either LexemeForm.Form or LexSense.Definition. We could probably
				// do this as part of the solution to handling duplicate columns in LT-3763.
				XmlNode column = columns[i] as XmlNode;
				string columnLabel = XmlUtils.GetManditoryAttributeValue(column, "label");
				string[] columnLabelComponents = columnLabel.Split(new char[] {' ', ':'});
				// get column label without writing system or extraneous information.
				string columnBasicLabel = columnLabelComponents[0];
				if (!String.IsNullOrEmpty(columnBasicLabel) && stringTbl != null)
					columnBasicLabel = stringTbl.LocalizeAttributeValue(columnBasicLabel);
				ITsTextProps ttp = rgtss[i].get_PropertiesAt(0);
				int var;
				int ws = ttp.GetIntPropValues((int)FwTextPropType.ktptWs, out var);
				Debug.Assert(ws != 0);

				ITsString tssStr = rgtss[i];
				string sStr = tssStr.Text;
				if (sStr == null)
					sStr = ""; // otherwise Trim below blows up.
				sStr = sStr.Trim();

				if (columnBasicLabel == Strings.ksWord)
				{
					// This is a lexeme form.

					if (morph == null)
						morph = MoForm.MakeMorph(cache, le, tssStr);
					Debug.Assert(le.LexemeFormOAHvo != 0);
					if (morph is IMoStemAllomorph)
					{
						// Make sure we have a proper allomorph and MSA for this new entry and sense.
						// (See LT-1318 for details and justification.)
						MoMorphTypeCollection typesCol = new MoMorphTypeCollection(cache);
						if (sStr.IndexOf(' ') > 0)
							morph.MorphTypeRA = typesCol.Item(MoMorphType.kmtPhrase);
						else
							morph.MorphTypeRA = typesCol.Item(MoMorphType.kmtStem);
						morph.Form.SetAlternative(sStr, ws);
					}
				}
				else if (columnBasicLabel == Strings.ksDefinition)
				{
					// This is a Definition.
					if (sStr != "")
						ls.Definition.SetAlternative(sStr, ws);
				}
				else
				{
					Debug.Fail("column (" + columnLabel + ") not supported.");
				}
			}
			if (morph == null)
				morph = le.LexemeFormOA = new MoStemAllomorph();

			ls.RDEAddDomain(hvoDomain, tagList, cache);

			if (le.MorphoSyntaxAnalysesOC.Count == 0)
			{
				// Commonly, it's a new entry with no MSAs; make sure it has at least one.
				// This way of doing it allows a good bit of code to be shared with the normal
				// creation path, as if the user made a stem but didn't fill in any grammatical
				// information.
				DummyGenericMSA dummyMsa = new DummyGenericMSA();
				if (morph != null && morph is IMoAffixForm)
					dummyMsa.MsaType = MsaType.kUnclassified;
				else
					dummyMsa.MsaType = MsaType.kStem;
				ls.DummyMSA = dummyMsa;
			}

			// We don't want a partial MSA created, so don't bother doing anything
			// about setting ls.MorphoSyntaxAnalysisRA

			// LT-1731: adding to make sure new entries are added to the lexicon
			//	record list (full edit,...)
			cache.PropChanged(null, PropChangeType.kpctNotifyAll,
				cache.LangProject.LexDbOA.Hvo,
				(int)LexDb.LexDbTags.kflidEntries, 0, 1, 0);

			return ls.Hvo;
		}
Example #19
0
		/// <summary>
		/// Get a set of hvos that are suitable for targets to a reference property.
		/// Subclasses should override this method to return a sensible list of IDs.
		/// </summary>
		/// <param name="flid">The reference property that can store the IDs.</param>
		/// <returns>A set of hvos.</returns>
		public override Set<int> ReferenceTargetCandidates(int flid)
		{
			Set<int> set = null;
			switch (flid)
			{
				case (int)MoForm.MoFormTags.kflidMorphType:
					set = new Set<int>(m_cache.LangProject.LexDbOA.MorphTypesOA.PossibilitiesOS.HvoArray);
					// Remove affix types.
					MoMorphTypeCollection types = new MoMorphTypeCollection(m_cache);
					set.Remove(types.Item(MoMorphType.kmtCircumfix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtInfix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtPrefix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtSimulfix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtSuffix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtSuprafix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtInfixingInterfix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtPrefixingInterfix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtSuffixingInterfix).Hvo);
					break;
				case (int)MoStemAllomorph.MoStemAllomorphTags.kflidPhoneEnv:
					set = PhEnvironment.ValidEnvironments(m_cache);
					break;
				case (int)MoStemAllomorph.MoStemAllomorphTags.kflidStemName:
					set = new Set<int>();
					//List<CmPossibility> poses = m_cache.LangProject.PartsOfSpeechOA.ReallyReallyAllPossibilities;
					int ownerID = OwnerHVO;
					int ownerClass = m_cache.GetIntProperty(ownerID, (int)CmObjectFields.kflidCmObject_Class);
					if (ownerClass == LexEntry.kclsidLexEntry)
					{
						ILexEntry entry = LexEntry.CreateFromDBObject(m_cache, ownerID);
						foreach (IMoMorphSynAnalysis msa in entry.MorphoSyntaxAnalysesOC)
						{
							if (msa is IMoStemMsa)
							{
								IMoStemMsa infstemmsa = (IMoStemMsa)msa;
								IPartOfSpeech pos = infstemmsa.PartOfSpeechRA;
								if (pos != null)
								{
									foreach (IMoStemName sn in pos.AllStemNames)
										set.Add(sn.Hvo);
								}
							}
						}
					}
					break;
				default:
					set = base.ReferenceTargetCandidates(flid);
					break;
			}
			return set;
		}
Example #20
0
		static private void SplitCircumfixIntoLeftAndRightAllomorphs(FdoCache cache,
			ILexEntry entry, ITsString tssLexemeForm, ILexSense sense)
		{
			string sLeftMember;
			string sRightMember;
			if (!GetCircumfixLeftAndRightParts(cache, tssLexemeForm, out sLeftMember, out sRightMember))
				return;
			// Create left and right allomorphs
			int wsVern = StringUtils.GetWsAtOffset(tssLexemeForm, 0);
			IMoMorphType mmtPrefix;
			IMoMorphType mmtSuffix;
			IMoMorphType mmtInfix;
			MoMorphType.GetMajorAffixMorphTypes(cache, out mmtPrefix, out mmtSuffix, out mmtInfix);
			int clsidForm;
			MoMorphTypeCollection mmtCol = new MoMorphTypeCollection(cache);
			IMoMorphType mmt = MoMorphType.FindMorphType(cache, mmtCol, ref sLeftMember, out clsidForm);
			if ((mmt.Hvo != mmtPrefix.Hvo) &&
				(mmt.Hvo != mmtInfix.Hvo))
				mmt = mmtPrefix; // force a prefix if it's neither a prefix nor an infix
			IMoForm allomorph = MoForm.CreateAllomorph(entry, sense.MorphoSyntaxAnalysisRA,
				StringUtils.MakeTss(sLeftMember, wsVern), mmt, false);
			mmt = MoMorphType.FindMorphType(cache, mmtCol, ref sRightMember, out clsidForm);
			if ((mmt.Hvo != mmtInfix.Hvo) &&
				(mmt.Hvo != mmtSuffix.Hvo))
				mmt = mmtSuffix; // force a suffix if it's neither a suffix nor an infix
			allomorph = MoForm.CreateAllomorph(entry, sense.MorphoSyntaxAnalysisRA,
				StringUtils.MakeTss(sRightMember, wsVern), mmt, false);
		}
Example #21
0
		/// <summary>
		///
		/// </summary>
		/// <param name="hvoAnalysisIn">either m_hvoAnalysis, m_hvoPrevAnal, or m_hvoNextAnal
		/// </param>
		/// <param name="hvoWordformRef">reference to either m_hvoWordform, m_hvoPrevWordform,
		/// or m_hvoNextWordform</param>
		/// <param name="hvoSbWord">either m_hvoSbWord, m_hvoPrevSbWordb, or m_hvoNextSbWord
		/// </param>
		/// <param name="fAdjustCase">If true, may adjust case of morpheme when
		/// proposing whole word as default morpheme breakdown.</param>
		/// <returns>true if any guessing is involved.</returns>
		private bool LoadRealDataIntoSec1(ref int hvoAnalysisRef, out int hvoWordformRef,
			int hvoSbWord, bool fLookForDefaults, bool fAdjustCase)
		{
			int wsAnalysis = m_caches.MainCache.DefaultAnalWs;
			ITsStrFactory tsf = TsStrFactoryClass.Create();
			IVwCacheDa cda = (IVwCacheDa)m_caches.DataAccess;
			if (hvoAnalysisRef == 0)
			{
				hvoWordformRef = 0;
				// should we empty the cache of any stale data?
				return false;
			}
			m_hvoLastSelEntry = 0;	// forget last Lex Entry user selection. We're resync'ing everything.
			int hvoAnalysis = 0;
			m_hvoWordGloss = 0;
			int fGuessing = 0;  // Use 0 or 1, as we store it in an int dummy property.


			switch (m_caches.MainCache.GetClassOfObject(hvoAnalysisRef))
			{
				case WfiWordform.kclsidWfiWordform:
					hvoWordformRef = hvoAnalysisRef;
					break;
				case WfiAnalysis.kclsidWfiAnalysis:
					hvoAnalysis = hvoAnalysisRef;
					hvoWordformRef = m_caches.MainCache.GetOwnerOfObject(hvoAnalysis);
					break;
				case WfiGloss.kclsidWfiGloss:
					m_hvoWordGloss = hvoAnalysisRef;
					hvoAnalysis = m_caches.MainCache.GetOwnerOfObject(m_hvoWordGloss);
					hvoWordformRef = m_caches.MainCache.GetOwnerOfObject(hvoAnalysis);
					break;
				default:
					Debug.Assert(false, "analysis must be wordform, wfianalysis, or wfigloss");
					hvoWordformRef = 0;
					break;
			}
			RawWordform = null; // recompute based upon wordform.
			int wsVern = RawWordformWs;
			m_caches.Map(hvoSbWord, hvoWordformRef); // Review: any reason to map these?
			ISilDataAccess sdaMain = m_caches.MainCache.MainCacheAccessor;
			CopyStringsToSecondary(InterlinLineChoices.kflidWord, sdaMain, hvoWordformRef,
				(int)WfiWordform.WfiWordformTags.kflidForm, cda, hvoSbWord, ktagSbWordForm, tsf);
			CaseFunctions cf = VernCaseFuncs(RawWordform);
			m_case = cf.StringCase(RawWordform.Text);
			// empty it in case we're redoing after choose from combo.
			cda.CacheVecProp(hvoSbWord, ktagSbWordMorphs, new int[0], 0);
			if (hvoAnalysis == 0)
			{
				if (fLookForDefaults)
				{
					GetDefaults(hvoWordformRef, out hvoAnalysis, out m_hvoWordGloss, fAdjustCase);
					// Make sure the wordform ID is consistent with the analysis we located.
					if (hvoAnalysis != 0)
					{
						int hvoFixedWordform = m_caches.MainCache.GetOwnerOfObject(hvoAnalysis);
						if (hvoFixedWordform != hvoWordformRef)
						{
							hvoWordformRef = hvoFixedWordform;
							// Update the actual form.
							// Enhance: may NOT want to do this, when we get the baseline consistently
							// keeping original case.
							CopyStringsToSecondary(InterlinLineChoices.kflidWord, sdaMain, hvoWordformRef,
								(int)WfiWordform.WfiWordformTags.kflidForm, cda, hvoSbWord, ktagSbWordForm, tsf);
							hvoAnalysisRef = hvoFixedWordform;
						}
					}
					// Hide the analysis combo if there's no default analysis (which means there are
					// no options to list).
					m_fShowAnalysisCombo = (hvoAnalysis != 0);
					fGuessing = 1;
					// If we found a word gloss treat as human-approved.
					bool fHumanApproved = (m_hvoWordGloss != 0);
					if (!fHumanApproved)
					{
						// Human may have approved the analysis anyway.
						string sql = string.Format("select count(ag.id) " +
							"from CmAgentEvaluation_ ae " +
							"join CmAgent ag on ae.owner$ = ag.id and ae.target = {0} and ag.human = 1",
							hvoAnalysis);
						int nHumanApprovals;
						DbOps.ReadOneIntFromCommand(m_caches.MainCache, sql, null, out nHumanApprovals);
						fHumanApproved = (nHumanApprovals != 0);
					}
					this.GuessColor = fHumanApproved ? InterlinVc.ApprovedGuessColor : InterlinVc.MachineGuessColor;
				}
				else if (hvoWordformRef != 0)
				{
					// Need to check whether there are any options to list.
					m_fShowAnalysisCombo = m_caches.MainCache.GetVectorSize(hvoWordformRef,
						(int)WfiWordform.WfiWordformTags.kflidAnalyses) > 0;
				}
			}
			else
			{
				// If we got a definite analysis, at most we're guessing a gloss, which is always human-approved.
				this.GuessColor = InterlinVc.ApprovedGuessColor;
				m_fShowAnalysisCombo = true; // there's a real analysis!
			}
			m_hvoAnalysisGuess = hvoAnalysis;
			if (m_hvoWordGloss != 0)
				m_hvoAnalysisGuess = m_hvoWordGloss;

			// make the wordform corresponding to the baseline ws, match RawWordform
			m_caches.DataAccess.SetMultiStringAlt(kSbWord, ktagSbWordForm, this.RawWordformWs, RawWordform);
			// Set every alternative of the word gloss, whether or not we have one...this
			// ensures clearing it out if we once had something but do no longer.
			CopyStringsToSecondary(InterlinLineChoices.kflidWordGloss, sdaMain, m_hvoWordGloss,
				(int)WfiGloss.WfiGlossTags.kflidForm, cda, hvoSbWord, ktagSbWordGloss, tsf);
			cda.CacheIntProp(hvoSbWord, ktagSbWordGlossGuess, fGuessing);
			cda.CacheObjProp(hvoSbWord, ktagSbWordPos, 0); // default.
			if (hvoAnalysis != 0) // Might still be, if no default is available.
			{
				int hvoCategory = sdaMain.get_ObjectProp(hvoAnalysis,
					(int)WfiAnalysis.WfiAnalysisTags.kflidCategory);
				if (hvoCategory != 0)
				{
					int hvoWordPos = CreateSecondaryAndCopyStrings(InterlinLineChoices.kflidWordPos, hvoCategory,
						(int)CmPossibility.CmPossibilityTags.kflidAbbreviation, hvoSbWord, sdaMain, cda, tsf);
					cda.CacheObjProp(hvoSbWord, ktagSbWordPos, hvoWordPos);
					cda.CacheIntProp(hvoWordPos, ktagSbNamedObjGuess, fGuessing);
				}
				int cmorphs = 0;
				if (this.ShowMorphBundles)
					cmorphs = sdaMain.get_VecSize(hvoAnalysis,
						(int)WfiAnalysis.WfiAnalysisTags.kflidMorphBundles);
				MoMorphTypeCollection morphtypes = new MoMorphTypeCollection(m_caches.MainCache);
				for (int imorph = 0; imorph < cmorphs; ++imorph)
				{
					// Get the real morpheme bundle.
					int hvoMb = sdaMain.get_VecItem(hvoAnalysis,
						(int)WfiAnalysis.WfiAnalysisTags.kflidMorphBundles, imorph);
					// Create the corresponding SbMorph.
					int hvoMbSec = m_caches.DataAccess.MakeNewObject(kclsidSbMorph, hvoSbWord,
						ktagSbWordMorphs, imorph);
					m_caches.Map(hvoMbSec, hvoMb);

					// Get the real MoForm, if any.
					int hvoMorphReal = sdaMain.get_ObjectProp(hvoMb,
						(int)WfiMorphBundle.WfiMorphBundleTags.kflidMorph);
					// Get the text we will display on the first line of the morpheme bundle.
					// Taken from the MoForm if any, otherwise the form of the MB.
					int hvoMorphForm;
					string sPrefix = null;
					string sPostfix = null;
					if (hvoMorphReal == 0)
					{
						// Create the secondary object corresponding to the MoForm. We create one
						// even though there isn't a real MoForm. It doesn't correspond to anything
						// in the real database.
						hvoMorphForm = m_caches.DataAccess.MakeNewObject(kclsidSbNamedObj, hvoMb,
							ktagSbMorphForm, -2); // -2 for atomic
						CopyStringsToSecondary(InterlinLineChoices.kflidMorphemes, sdaMain, hvoMb,
							(int)WfiMorphBundle.WfiMorphBundleTags.kflidForm, cda, hvoMorphForm, ktagSbNamedObjName, tsf);
						// We will slightly adjust the form we display in the default vernacular WS.
						InterlinLineSpec specMorphemes = m_choices.GetPrimarySpec(InterlinLineChoices.kflidMorphemes);
						int wsForm = RawWordformWs;
						if (specMorphemes != null)
							wsForm = specMorphemes.GetActualWs(Cache, hvoMb, wsForm);
						ITsString tssForm = sdaMain.get_MultiStringAlt(hvoMb,
							(int)WfiMorphBundle.WfiMorphBundleTags.kflidForm,
							wsForm);
						string realForm = tssForm.Text;
						// currently (unfortunately) Text returns 'null' from COM for empty strings.
						if (realForm == null)
							realForm = string.Empty;

						// if it's not an empty string, then we can find its form type, and separate the
						// morpheme markers into separate properties.
						if (realForm != string.Empty)
						{
							IMoMorphType mmt = null;
							try
							{
								int clsidForm;
								mmt = MoMorphType.FindMorphType(m_caches.MainCache, morphtypes,
									ref realForm, out clsidForm);
								sPrefix = mmt.Prefix;
								sPostfix = mmt.Postfix;
							}
							catch (Exception e)
							{
								MessageBox.Show(null, e.Message, ITextStrings.ksWarning,
									MessageBoxButtons.OK);
							}
						}
						tssForm = StringUtils.MakeTss(realForm, RawWordformWs);
						cda.CacheStringAlt(hvoMorphForm, ktagSbNamedObjName, wsVern, tssForm);
					}
					else
					{
						// Create the secondary object corresponding to the MoForm in the usual way from the form object.
						hvoMorphForm = CreateSecondaryAndCopyStrings(InterlinLineChoices.kflidMorphemes, hvoMorphReal,
							(int)MoForm.MoFormTags.kflidForm, hvoSbWord, sdaMain, cda, tsf);
						// Store the prefix and postfix markers from the MoMorphType object.
						int hvoMorphType = sdaMain.get_ObjectProp(hvoMorphReal,
							(int)MoForm.MoFormTags.kflidMorphType);
						if (hvoMorphType != 0)
						{
							sPrefix = sdaMain.get_UnicodeProp(hvoMorphType,
								(int)MoMorphType.MoMorphTypeTags.kflidPrefix);
							sPostfix = sdaMain.get_UnicodeProp(hvoMorphType,
								(int)MoMorphType.MoMorphTypeTags.kflidPostfix);
						}
					}
					if (sPrefix != null && sPrefix != "")
						cda.CacheStringProp(hvoMbSec, ktagSbMorphPrefix,
							tsf.MakeString(sPrefix, wsVern));
					if (sPostfix != null && sPostfix != "")
						cda.CacheStringProp(hvoMbSec, ktagSbMorphPostfix,
							tsf.MakeString(sPostfix, wsVern));

					// Link the SbMorph to its form object, noting if it is a guess.
					cda.CacheObjProp(hvoMbSec, ktagSbMorphForm, hvoMorphForm);
					cda.CacheIntProp(hvoMorphForm, ktagSbNamedObjGuess, fGuessing);

					// Get the real Sense that supplies the gloss, if any.
					int hvoSenseReal = sdaMain.get_ObjectProp(hvoMb,
						(int)WfiMorphBundle.WfiMorphBundleTags.kflidSense);
					if (hvoSenseReal == 0)
					{
						// Guess a default
						int virtFlid = BaseVirtualHandler.GetInstalledHandlerTag(m_caches.MainCache, "WfiMorphBundle", "DefaultSense");
						hvoSenseReal = sdaMain.get_ObjectProp(hvoMb, virtFlid);
						this.GuessColor = InterlinVc.MachineGuessColor;
					}
					if (hvoSenseReal != 0) // either all-the-way real, or default.
					{
						// Create the corresponding dummy.
						int hvoSense = CreateSecondaryAndCopyStrings(InterlinLineChoices.kflidLexGloss, hvoSenseReal,
							(int)LexSense.LexSenseTags.kflidGloss, hvoSbWord, sdaMain, cda, tsf);
						cda.CacheObjProp(hvoMbSec, ktagSbMorphGloss, hvoSense);
						cda.CacheIntProp(hvoSense, ktagSbNamedObjGuess, fGuessing);
					}

					// Get the MSA, if any.
					int hvoMsaReal = sdaMain.get_ObjectProp(hvoMb,
						(int)WfiMorphBundle.WfiMorphBundleTags.kflidMsa);
					if (hvoMsaReal != 0)
					{
						MoMorphSynAnalysis msa = ((MoMorphSynAnalysis)CmObject.CreateFromDBObject(
							m_caches.MainCache, hvoMsaReal, false));
						int hvoPos = m_caches.FindOrCreateSec(hvoMsaReal,
							kclsidSbNamedObj, hvoSbWord, ktagSbWordDummy);

						// Enhance JohnT: we'd really rather be able to get an appropriate different name
						// for each ws, but not possible yet.
						// Enhancement RickM: now we can do this with InterlinAbbrTSS(ws)
						foreach (int ws in m_choices.WritingSystemsForFlid(InterlinLineChoices.kflidLexPos, true))
						{
							// Since ws maybe ksFirstAnal/ksFirstVern, we need to get what is actually
							// used in order to retrieve the data in Vc.Display().  See LT_7976.
							ITsString tssLexPos = msa.InterlinAbbrTSS(ws);
							int wsActual = StringUtils.GetWsAtOffset(tssLexPos, 0);
							cda.CacheStringAlt(hvoPos, ktagSbNamedObjName, wsActual, tssLexPos);
						}
						cda.CacheObjProp(hvoMbSec, ktagSbMorphPos, hvoPos);
						cda.CacheIntProp(hvoPos, ktagSbNamedObjGuess, fGuessing);
					}

					// If we have a form, we can get its owner and set the info for the Entry
					// line.
					// Enhance JohnT: attempt a guess if we have a form but no entry.
					if (hvoMorphReal != 0)
					{
						int hvoEntryReal = m_caches.MainCache.GetOwnerOfObject(hvoMorphReal);
						// We can assume the owner is a LexEntry as that is the only type of object
						// that can own MoForms. We don't actually create the LexEntry, to
						// improve performance. All the relevant data should already have
						// been loaded while creating the main interlinear view.
						LoadSecDataForEntry(hvoEntryReal, hvoSenseReal, hvoSbWord, cda, wsVern, hvoMbSec, fGuessing, sdaMain, tsf);
					}
				}
			}
			else
			{
				// No analysis, default or otherwise. We immediately, however, fill in a single
				// dummy morpheme, if showing morphology.
				fGuessing = 0;	// distinguish between a 'guess' (defaults) and courtesy filler info (cf. LT-5858).
				GuessColor = NoGuessColor;
				if (ShowMorphBundles)
				{
					int hvoMbSec = m_caches.DataAccess.MakeNewObject(kclsidSbMorph, hvoSbWord,
						ktagSbWordMorphs, 0);
					ITsString tssForm = m_caches.DataAccess.get_MultiStringAlt(hvoSbWord, ktagSbWordForm, this.RawWordformWs);
					// Possibly adjust case of tssForm.
					if (fAdjustCase && CaseStatus == StringCaseStatus.title &&
						tssForm != null && tssForm.Length > 0)
					{
						tssForm = StringUtils.MakeTss(cf.ToLower(tssForm.Text), this.RawWordformWs);
						if (m_tssWordform != null)
							Marshal.ReleaseComObject(m_tssWordform);
						m_tssWordform = tssForm; // need this to be set in case hvoWordformRef set to zero.
						// If we adjust the case of the form, we must adjust the hvo as well,
						// or any analyses created will go to the wrong WfiWordform.
						hvoWordformRef = GetWordform(tssForm);
						if (hvoWordformRef != 0)
							m_fShowAnalysisCombo = m_caches.MainCache.GetVectorSize(hvoWordformRef,
								(int)WfiWordform.WfiWordformTags.kflidAnalyses) > 0;
					}
					else
					{
						// just use the wfi wordform form for our dummy morph form.
						tssForm = m_caches.MainCache.GetMultiStringAlt(hvoWordformRef, (int)WfiWordform.WfiWordformTags.kflidForm, this.RawWordformWs);
					}
					int hvoMorphForm = m_caches.FindOrCreateSec(0, kclsidSbNamedObj,
						hvoSbWord, ktagSbWordDummy);
					cda.CacheStringAlt(hvoMorphForm, ktagSbNamedObjName, wsVern, tssForm);
					cda.CacheObjProp(hvoMbSec, ktagSbMorphForm, hvoMorphForm);
					cda.CacheIntProp(hvoMorphForm, ktagSbNamedObjGuess, fGuessing);
				}
			}
			return fGuessing != 0;
		}