override public IWfiWordform SetAlternateCase(int iSegment, int iSegForm, StringCaseStatus targetState, out string alternateCaseForm) { IWfiWordform wfAlternateCase = base.SetAlternateCase(iSegment, iSegForm, targetState, out alternateCaseForm); m_pb.SetExpectedValuesForAnalysis(m_pb.SegmentFormNode(iSegment, iSegForm), wfAlternateCase.Hvo); return wfAlternateCase; }
virtual public IWfiWordform SetAlternateCase(int iSegment, int iSegForm, StringCaseStatus targetState, out string alternateCaseForm) { // Get actual segment form. var analysisActual = GetAnalysis(iSegment, iSegForm); int hvoActualInstanceOf; IWfiWordform actualWordform; GetRealWordformInfo(analysisActual, out hvoActualInstanceOf, out actualWordform); ITsString tssWordformBaseline = GetBaselineText(iSegment, iSegForm); // Add any relevant 'other case' forms. int nvar; int ws = tssWordformBaseline.get_Properties(0).GetIntPropValues((int)FwTextPropType.ktptWs, out nvar); string locale = m_cache.ServiceLocator.WritingSystemManager.Get(ws).IcuLocale; var cf = new CaseFunctions(locale); switch (targetState) { case StringCaseStatus.allLower: alternateCaseForm = cf.ToLower(actualWordform.Form.get_String(ws).Text); break; default: throw new ArgumentException("target StringCaseStatus(" + targetState + ") not yet supported."); } // Find or create the new wordform. IWfiWordform wfAlternateCase = WfiWordformServices.FindOrCreateWordform(m_cache, TsStringUtils.MakeTss(alternateCaseForm, ws)); // Set the annotation to this wordform. SetAnalysis(iSegment, iSegForm, wfAlternateCase); return wfAlternateCase; }
override internal IWfiWordform SetAlternateCase(string wordform, int iOccurrenceInParagraph, StringCaseStatus targetState) { int iSegment = -1; int iSegForm = -1; m_pb.GetSegmentFormInfo(wordform, iOccurrenceInParagraph, out iSegment, out iSegForm); string alternateWordform; return SetAlternateCase(iSegment, iSegForm, targetState, out alternateWordform); }
/// <summary> /// /// </summary> /// <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(int hvoSbWord, bool fLookForDefaults, bool fAdjustCase) { ITsStrFactory tsf = TsStrFactoryClass.Create(); IVwCacheDa cda = (IVwCacheDa)m_caches.DataAccess; if (CurrentAnalysisTree.Analysis == null) { // 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. IWfiAnalysis analysis = CurrentAnalysisTree.WfiAnalysis; IWfiGloss gloss = CurrentAnalysisTree.Gloss; m_hvoWordGloss = gloss != null ? gloss.Hvo : 0; int fGuessing = 0; // Use 0 or 1, as we store it in an int dummy property. RawWordform = null; // recompute based upon wordform. int wsVern = RawWordformWs; m_caches.Map(hvoSbWord, CurrentAnalysisTree.Wordform.Hvo); // Review: any reason to map these? ISilDataAccess sdaMain = m_caches.MainCache.MainCacheAccessor; CopyStringsToSecondary(InterlinLineChoices.kflidWord, sdaMain, CurrentAnalysisTree.Wordform.Hvo, 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 (analysis == null) { if (fLookForDefaults) { GetDefaults(CurrentAnalysisTree.Wordform, out analysis, out gloss, fAdjustCase); m_hvoWordGloss = gloss != null ? gloss.Hvo : 0; // Make sure the wordform ID is consistent with the analysis we located. if (analysis != null) { //set the color before we fidle with our the wordform, it right for this purpose now. if (GetHasMultipleRelevantAnalyses(CurrentAnalysisTree.Wordform)) { MultipleAnalysisColor = InterlinVc.MultipleApprovedGuessColor; } var fixedWordform = analysis.Owner as IWfiWordform; if (fixedWordform != CurrentAnalysisTree.Wordform) { CurrentAnalysisTree.Analysis = fixedWordform; // Update the actual form. // Enhance: may NOT want to do this, when we get the baseline consistently // keeping original case. CopyStringsToSecondary(InterlinLineChoices.kflidWord, sdaMain, CurrentAnalysisTree.Wordform.Hvo, WfiWordformTags.kflidForm, cda, hvoSbWord, ktagSbWordForm, tsf); } } // Hide the analysis combo if there's no default analysis (which means there are // no options to list). m_fShowAnalysisCombo = (analysis != null); fGuessing = 1; } else if (CurrentAnalysisTree.Wordform != null) { // Need to check whether there are any options to list. m_fShowAnalysisCombo = CurrentAnalysisTree.Wordform.AnalysesOC.Count > 0; } } else { m_fShowAnalysisCombo = true; // there's a real analysis! } m_hvoAnalysisGuess = analysis != null ? analysis.Hvo : 0; 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, WfiGlossTags.kflidForm, cda, hvoSbWord, ktagSbWordGloss, tsf); cda.CacheIntProp(hvoSbWord, ktagSbWordGlossGuess, fGuessing); cda.CacheObjProp(hvoSbWord, ktagSbWordPos, 0); // default. if (analysis != null) // Might still be, if no default is available. { var category = analysis.CategoryRA; if (category != null) { int hvoWordPos = CreateSecondaryAndCopyStrings(InterlinLineChoices.kflidWordPos, category.Hvo, CmPossibilityTags.kflidAbbreviation, hvoSbWord, sdaMain, cda, tsf); cda.CacheObjProp(hvoSbWord, ktagSbWordPos, hvoWordPos); cda.CacheIntProp(hvoWordPos, ktagSbNamedObjGuess, fGuessing); } if (this.ShowMorphBundles) { var bldrError = new StringBuilder(); foreach (var mb in analysis.MorphBundlesOS) { // Create the corresponding SbMorph. int hvoMbSec = m_caches.DataAccess.MakeNewObject(kclsidSbMorph, hvoSbWord, ktagSbWordMorphs, mb.IndexInOwner); m_caches.Map(hvoMbSec, mb.Hvo); // Get the real MoForm, if any. var mf = mb.MorphRA; // 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 (mf == null) { // 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, mb.Hvo, ktagSbMorphForm, -2); // -2 for atomic CopyStringsToSecondary(InterlinLineChoices.kflidMorphemes, sdaMain, mb.Hvo, 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; if (specMorphemes == null || !mb.Form.TryWs(specMorphemes.WritingSystem, out wsForm)) wsForm = RawWordformWs; ITsString tssForm = sdaMain.get_MultiStringAlt(mb.Hvo, 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 = MorphServices.FindMorphType(m_caches.MainCache, ref realForm, out clsidForm); sPrefix = mmt.Prefix; sPostfix = mmt.Postfix; } catch (Exception e) { bldrError.AppendLine(e.Message); } } tssForm = TsStringUtils.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, mf.Hvo, MoFormTags.kflidForm, hvoSbWord, sdaMain, cda, tsf); // Store the prefix and postfix markers from the MoMorphType object. int hvoMorphType = sdaMain.get_ObjectProp(mf.Hvo, MoFormTags.kflidMorphType); if (hvoMorphType != 0) { sPrefix = sdaMain.get_UnicodeProp(hvoMorphType, MoMorphTypeTags.kflidPrefix); sPostfix = sdaMain.get_UnicodeProp(hvoMorphType, MoMorphTypeTags.kflidPostfix); } } if (!String.IsNullOrEmpty(sPrefix)) cda.CacheStringProp(hvoMbSec, ktagSbMorphPrefix, tsf.MakeString(sPrefix, wsVern)); if (!String.IsNullOrEmpty(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. var senseReal = mb.SenseRA; if (senseReal == null && fGuessing != 0) { // Guess a default senseReal = mb.DefaultSense; } if (senseReal != null) // either all-the-way real, or default. { // Create the corresponding dummy. int hvoLexSenseSec; // Add any irregularly inflected form type info to the LexGloss. ILexEntryRef lerTest; ILexEntry possibleVariant = null; if (mf != null) possibleVariant = mf.Owner as ILexEntry; if (possibleVariant != null && possibleVariant.IsVariantOfSenseOrOwnerEntry(senseReal, out lerTest)) { hvoLexSenseSec = m_caches.FindOrCreateSec(senseReal.Hvo, kclsidSbNamedObj, hvoSbWord, ktagSbWordDummy); CacheLexGlossWithInflTypeForAllCurrentWs(possibleVariant, hvoLexSenseSec, wsVern, cda, mb.InflTypeRA); } else { // add normal LexGloss without variant info hvoLexSenseSec = CreateSecondaryAndCopyStrings(InterlinLineChoices.kflidLexGloss, senseReal.Hvo, LexSenseTags.kflidGloss, hvoSbWord, sdaMain, cda, tsf); } cda.CacheObjProp(hvoMbSec, ktagSbMorphGloss, hvoLexSenseSec); cda.CacheIntProp(hvoLexSenseSec, ktagSbNamedObjGuess, fGuessing); int hvoInflType = 0; if (mb.InflTypeRA != null) { hvoInflType = m_caches.FindOrCreateSec(mb.InflTypeRA.Hvo, kclsidSbNamedObj, hvoSbWord, ktagSbWordDummy); } cda.CacheObjProp(hvoMbSec, ktagSbNamedObjInflType, hvoInflType); } // Get the MSA, if any. var msaReal = mb.MsaRA; if (msaReal != null) { int hvoPos = m_caches.FindOrCreateSec(msaReal.Hvo, kclsidSbNamedObj, hvoSbWord, ktagSbWordDummy); 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. // Use InterlinAbbrTss to get an appropriate different name for each ws ITsString tssLexPos = msaReal.InterlinAbbrTSS(ws); int wsActual = TsStringUtils.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 (mf != null) { var entryReal = mf.Owner as ILexEntry; // 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(entryReal, senseReal, hvoSbWord, cda, wsVern, hvoMbSec, fGuessing, sdaMain, tsf); } } if (bldrError.Length > 0) { var msg = bldrError.ToString().Trim(); var wnd = (FindForm() ?? Mediator.PropertyTable.GetValue("window")) as IWin32Window; MessageBox.Show(wnd, msg, ITextStrings.ksWarning, MessageBoxButtons.OK, MessageBoxIcon.Warning); } } } 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). 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 = TsStringUtils.MakeTss(cf.ToLower(tssForm.Text), this.RawWordformWs); 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. CurrentAnalysisTree.Analysis = GetWordform(tssForm); if (CurrentAnalysisTree.Wordform != null) m_fShowAnalysisCombo = CurrentAnalysisTree.Wordform.AnalysesOC.Count > 0; } else { // just use the wfi wordform form for our dummy morph form. tssForm = CurrentAnalysisTree.Wordform.Form.get_String(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; }
virtual internal IWfiWordform SetAlternateCase(string wordform, int iOccurrenceInParagraph, StringCaseStatus targetState) { return null; // override }
/// <summary> /// Load the real data into the secondary cache. /// </summary> /// <param name="fAdjustCase">If true, may adjust case of morpheme when /// proposing whole word as default morpheme breakdown.</param> /// <param name="fLookForDefaults">If true, will try to guess most likely analysis.</param> /// <param name="fClearDirty">if true, establishes the loaded cache state for the sandbox, /// so that subsequent changes can be undone or saved with respect to this initial state.</param> private void LoadRealDataIntoSec(bool fLookForDefaults, bool fAdjustCase, bool fClearDirty) { IVwCacheDa cda = (IVwCacheDa)m_caches.DataAccess; cda.ClearAllData(); m_caches.ClearMaps(); // If we don't have a real root object yet, we can't set anything up. if (CurrentAnalysisTree.Analysis == null) { // This probably paranoid, but it's safe. Debug.WriteLine("loading Sandbox for missing analysis"); m_wordformOriginal = null; m_case = StringCaseStatus.allLower; return; } // stop monitoring cache since we are about to make some drastic changes. using (new SandboxEditMonitorHelper(m_editMonitor, true)) { UsingGuess = LoadRealDataIntoSec1(kSbWord, fLookForDefaults, fAdjustCase); Debug.Assert(CurrentAnalysisTree.Wordform != null || m_tssWordform != null); // At this point the only reason to force the current displayed analysis // to be returned instead of the original is if we're guessing. //m_fForceReturnNewAnalysis = fGuessing; // Treat initial state (including guessing) as something you can leave without saving. // Make sure it doesn't think any edits have happened, even if reusing from some other word. if (fClearDirty) MarkAsInitialState(); } }
override internal int SetAlternateCase(int iSegment, int iSegForm, StringCaseStatus targetState, out string alternateCaseForm) { int hvoWfAlternateCase = base.SetAlternateCase(iSegment, iSegForm, targetState, out alternateCaseForm); int hvoCbaExpected = GetExpectedSegmentForm(iSegment, iSegForm); SetInstanceOf(hvoCbaExpected, hvoWfAlternateCase, false); return hvoWfAlternateCase; }
virtual internal int SetAlternateCase(int iSegment, int iSegForm, StringCaseStatus targetState, out string alternateCaseForm) { // Get actual segment form. int hvoCbaActual = GetSegmentForm(iSegment, iSegForm); int hvoActualInstanceOf; IWfiWordform actualCbaWordform; GetRealWordformInfo(hvoCbaActual, out hvoActualInstanceOf, out actualCbaWordform); ITsString tssWordformBaseline = GetBaselineText(hvoCbaActual); // Add any relevant 'other case' forms. int nvar; int ws = tssWordformBaseline.get_Properties(0).GetIntPropValues((int)FwTextPropType.ktptWs, out nvar); ; string locale = m_cache.LanguageWritingSystemFactoryAccessor.get_EngineOrNull(ws).IcuLocale; CaseFunctions cf = new CaseFunctions(locale); switch (targetState) { case StringCaseStatus.allLower: alternateCaseForm = cf.ToLower(actualCbaWordform.Form.GetAlternative(ws)); break; default: throw new ArgumentException("target StringCaseStatus(" + targetState.ToString() + ") not yet supported."); } // Find or create the new wordform. IWfiWordform wfAlternateCase = WfiWordform.FindOrCreateWordform(m_cache, alternateCaseForm, ws); // Set the annotation to this wordform. int hvoCbaReal = SetInstanceOf(hvoCbaActual, wfAlternateCase.Hvo, true); if (!tssWordformBaseline.Equals(wfAlternateCase.Form.BestVernacularAlternative)) { // Cache the real form. m_cache.VwCacheDaAccessor.CacheStringProp(hvoCbaReal, InterlinVc.TwficRealFormTag(m_cache), tssWordformBaseline); } return wfAlternateCase.Hvo; }
/// <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; }
/// <summary> /// Load the real data into the secondary cache. /// </summary> /// <param name="fAdjustCase">If true, may adjust case of morpheme when /// proposing whole word as default morpheme breakdown.</param> /// <param name="fLookForDefaults">If true, will try to guess most likely analysis.</param> /// <param name="fClearDirty">if true, establishes the loaded cache state for the sandbox, /// so that subsequent changes can be undone or saved with respect to this initial state.</param> private void LoadRealDataIntoSec(bool fLookForDefaults, bool fAdjustCase, bool fClearDirty) { IVwCacheDa cda = (IVwCacheDa)m_caches.DataAccess; cda.ClearAllData(); m_caches.ClearMaps(); // If we don't have a real root object yet, we can't set anything up. if (m_hvoAnalysis == 0) { // This probably paranoid, but it's safe. Debug.WriteLine("loading Sandbox for missing analysis"); m_hvoWordform = 0; m_hvoWordformOriginal = 0; m_case = StringCaseStatus.allLower; return; } m_fGuessing = LoadRealDataIntoSec1(ref m_hvoAnalysis, out m_hvoWordform, kSbWord, fLookForDefaults, fAdjustCase); Debug.Assert(m_hvoWordform != 0 || m_tssWordform != null); // At this point the only reason to force the current displayed analysis // to be returned instead of the original is if we're guessing. //m_fForceReturnNewAnalysis = fGuessing; // Treat initial state (including guessing) as something you can leave without saving. if (fClearDirty) MarkAsInitialState(); // Make sure it doesn't think any edits have happened, even if reusing from some other word. }