// public event EventHandler<string> Merged; public FlexImporter(FdoCache cache) { _cache = cache; _flexMorphTypes = new MoMorphTypeCollection(_cache); }
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); } }
/// <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; }
/// <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; }
/// <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; }
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; }
/// <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)); }
/// <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; }
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); }
/// <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; }
public FlexConverter(FdoCache cache) : base() { m_cache = cache; m_rgmmt = new MoMorphTypeCollection(m_cache); m_wsEn = m_cache.LanguageWritingSystemFactoryAccessor.GetWsFromStr("en"); }
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; } } }
/// <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); }
/// <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; }
protected override void SetDlgInfo(FdoCache cache, WindowParams wp, Mediator mediator, int wsVern) { CheckDisposed(); m_types = new MoMorphTypeCollection(cache); base.SetDlgInfo(cache, wp, mediator, wsVern); }
/// <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; }
/// <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; }
/// <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; }
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); }
/// <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; }