/// <summary> /// Initialize the required inventories. /// </summary> private void InitializePartInventories(FdoCache cache, bool fLoadUserOverrides) { WriteSplashScreen(LexTextStrings.ksInitializingLayouts_); LayoutCache.InitializePartInventories(false, cache.DatabaseName, fLoadUserOverrides); int flid = BaseVirtualHandler.GetInstalledHandlerTag(cache, "LexDb", "CurrentReversalIndices"); if (flid == 0) flid = (int)LexDb.LexDbTags.kflidReversalIndexes; int[] rghvoIndexes = cache.GetVectorProperty(cache.LangProject.LexDbOA.Hvo, flid, false); foreach (int hvoIndex in rghvoIndexes) { int ws = cache.GetObjProperty(hvoIndex, (int)ReversalIndex.ReversalIndexTags.kflidWritingSystem); string sWs = cache.GetUnicodeProperty(ws, (int)LgWritingSystem.LgWritingSystemTags.kflidICULocale); LayoutCache.InitializeLayoutsForWsTag(sWs, cache.DatabaseName); } }
/// <summary> /// Clean up anything we can find that uses the old dummy wordform. /// For each occurrence of the dummy wordform, update the Twfic's InstanceOf. /// Iterate over the Occurrences property to find them. /// </summary> /// <param name="fdoCache"></param> /// <param name="hvoDummyWordform"></param> /// <param name="hvoRealWordform"></param> internal static void CleanupDummyWordformReferences(FdoCache fdoCache, int hvoDummyWordform, int hvoRealWordform) { ISilDataAccess sda = fdoCache.MainCacheAccessor; int kflidOccurrences = WfiWordform.OccurrencesFlid(fdoCache); IVwCacheDa cda = fdoCache.VwCacheDaAccessor; int[] occurrences = fdoCache.GetVectorProperty(hvoDummyWordform, kflidOccurrences, true); for (int i = 0; i < occurrences.Length; i++) { int hvoDummyOccurrence = occurrences[i]; cda.CacheObjProp(hvoDummyOccurrence, (int)CmAnnotation.CmAnnotationTags.kflidInstanceOf, hvoRealWordform); int ownerPrev = fdoCache.GetObjProperty(hvoDummyOccurrence, (int)CmObjectFields.kflidCmObject_Owner); if (ownerPrev == hvoDummyWordform) cda.CacheObjProp(hvoDummyOccurrence, (int)CmObjectFields.kflidCmObject_Owner, hvoRealWordform); } cda.CacheVecProp(hvoRealWordform, kflidOccurrences, occurrences, occurrences.Length); }
/// <summary> /// Finds the wfiAnalysis the given wfic cba.InstanceOf. If it's an InstanceOf a WfiWordform, /// it'll return the wfiAnalysis of the guess, if found, otherwise it'll return the wfiWordform's first analysis. /// </summary> /// <param name="cache"></param> /// <param name="hvoCba"></param> /// <returns></returns> public static int GetWfiAnalysisFromInstanceOf(FdoCache cache, int hvoCba) { int cbaInstanceOf = cache.GetObjProperty(hvoCba, (int)CmAnnotation.CmAnnotationTags.kflidInstanceOf); Debug.Assert(cbaInstanceOf != 0); int hvoWordform; int hvoWfiAnalysis = GetWfiAnalysisFromWficInstanceOf(cache, cbaInstanceOf, out hvoWordform); if (hvoWfiAnalysis == 0 && hvoWordform != 0) { // we are probably an instance of a wordform. Try to use a guess or else use first analysis. int[] analyses = cache.GetVectorProperty(hvoWordform, (int)WfiWordform.WfiWordformTags.kflidAnalyses, false); if (analyses.Length > 0) { // first see if we have a guess we can use. int ktagTwficDefault = StTxtPara.TwficDefaultFlid(cache); int hvoTwficAnalysisGuess = cache.GetObjProperty(hvoCba, ktagTwficDefault); if (hvoTwficAnalysisGuess != 0) hvoWfiAnalysis = GetWfiAnalysisFromWficInstanceOf(cache, hvoTwficAnalysisGuess, out hvoWordform); if (hvoWfiAnalysis == 0) { if (analyses.Length > 1) { throw new ArgumentException( "Couldn't find a guess for a twfic with multiple analyses. Not sure which analysis to return."); } // since we have more than one Analyses, just return the first one. hvoWfiAnalysis = (int) analyses[0]; } } } return hvoWfiAnalysis; }
/// <summary> /// Updates ConcordanceWordform if it's in the cache. /// Enhance: We could refactor this to call a more generic FdoCache.TryUpdatingVector(). /// </summary> /// <param name="fdoCache"></param> /// <param name="hvoOldWordform">if 0, we'll insert hvoNewWordform at the end of the list.</param> /// <param name="hvoNewWordform">if 0, we'll delete hvoOldWordform from the list.</param> /// <returns>true, if it updated the vector, false if it didn't.</returns> internal static bool TryUpdatingConcordanceWordforms(FdoCache fdoCache, int hvoOldWordform, int hvoNewWordform) { ISilDataAccess sda = fdoCache.MainCacheAccessor; IVwCacheDa cda = fdoCache.VwCacheDaAccessor; // If WFI has ConcordanceWordforms property, replace hvoOldWordform with hvoNewWordform in it. int kflidConcordanceWordforms = WordformInventory.ConcordanceWordformsFlid(fdoCache); int hvoWfi = fdoCache.LangProject.WordformInventoryOAHvo; if (sda.get_IsPropInCache(hvoWfi, kflidConcordanceWordforms, (int)CellarModuleDefns.kcptReferenceSequence, 0)) { List<int> wordforms = new List<int>(fdoCache.GetVectorProperty(hvoWfi, kflidConcordanceWordforms, true)); // if wordforms.Count == 0, we must be in a context that has affected the wordforms, // but doesn't want to take direct responsibility for maintaining this list. if (wordforms.Count == 0) { return false; } int ihvoWfNew = wordforms.IndexOf(hvoNewWordform); Debug.Assert(ihvoWfNew == -1, "We are trying to insert a new wordform, but it's already in the concordance."); int[] newItems = ihvoWfNew == -1 && hvoNewWordform != 0 ? new int[] { hvoNewWordform } : new int[0]; CacheReplaceOneUndoAction cacheReplaceOccurrenceAction; if (hvoOldWordform != 0) { // we are trying replacing an existing wordform in the ConcordanceWordforms. int ihvoWf = wordforms.IndexOf(hvoOldWordform); Debug.Assert(ihvoWf != -1, "We are trying to remove an old wordform, but it's not in the concordance."); if (ihvoWf >= 0) { cacheReplaceOccurrenceAction = new CacheReplaceOneUndoAction(fdoCache, hvoWfi, kflidConcordanceWordforms, ihvoWf, ihvoWf + 1, newItems); cacheReplaceOccurrenceAction.DoIt(); return true; } return false; } else if (ihvoWfNew == -1 && hvoNewWordform != 0) { // we are inserting a new wordform in ConcordanceWordforms. add it to the end of the list. cacheReplaceOccurrenceAction = new CacheReplaceOneUndoAction(fdoCache, hvoWfi, kflidConcordanceWordforms, wordforms.Count, wordforms.Count, newItems); cacheReplaceOccurrenceAction.DoIt(); return true; } } return false; }
/// <summary> /// If hvoWordform is the hvo of a capitalized wordform which has no useful information, /// delete it. It is considered useless if /// - it has no occurrences /// - it has no anlyses /// - it doesn't have known incorrect spelling status. /// Note that the argument may be some other kind of object (typically a WfiAnalysis or WfiGloss). /// If so do nothing. /// </summary> public static void DeleteRedundantCapitalizedWordform(FdoCache cache, int hvoWordform) { if (cache.GetClassOfObject(hvoWordform) != WfiWordform.kclsidWfiWordform) return; if (cache.GetVectorProperty(hvoWordform, OccurrencesFlid(cache), true).Length != 0) return; if (cache.IsValidObject(hvoWordform)) { // If it's real it might have analyses etc. WfiWordform wf = (WfiWordform) CmObject.CreateFromDBObject(cache, hvoWordform); if (wf.AnalysesOC.Count > 0) return; // Arguably we should keep it for known correct spelling status. However, if it's ever been // confirmed as an analysis, even temporarily, it will have that. if (wf.SpellingStatus == (int)SpellingStatusStates.incorrect) return; } foreach (int ws in cache.LangProject.CurVernWssRS.HvoArray) { CaseFunctions cf = new CaseFunctions(cache.LanguageWritingSystemFactoryAccessor.get_EngineOrNull(ws).IcuLocale); string text = cache.GetMultiStringAlt(hvoWordform, (int) WfiWordformTags.kflidForm, ws).Text; if (!String.IsNullOrEmpty(text) && cf.StringCase(text) == StringCaseStatus.allLower) return; } cache.DeleteObject(hvoWordform); }
// Get the current value of the segments property -- or null, if it isn't cached or hasn't changed. int[] GetChangedSegments(FdoCache cache) { int kflidSegments = StTxtPara.SegmentsFlid(cache); if (cache.MainCacheAccessor.get_IsPropInCache(m_hvoPara, kflidSegments, (int)CellarModuleDefns.kcptReferenceSequence, 0)) { int[] result = cache.GetVectorProperty(m_hvoPara, StTxtPara.SegmentsFlid(cache), true); if (!SameIntArray(result, m_segments)) return result; } return null; }
static internal int[] GetCbasPotentiallyAffectedByTextEdit(FdoCache cache, int hvo, string sql) { IVwVirtualHandler vh = DummyVirtualHandler.InstallDummyHandler(cache.VwCacheDaAccessor, "StTxtPara", "CbasAffectedByEdit", (int)FieldType.kcptReferenceSequence); LoadAnnotationResults(cache, sql, vh.Tag); int[] cbaHvosAffectedByEdit = cache.GetVectorProperty(hvo, vh.Tag, true); // after getting the cached cbas, clear the list, so we will load it again // next time. Otherwise, LoadAnnotationResults, may (for some unknown reason) keep old data // and not load the new. (vh as DummyVirtualHandler).Load(hvo, 0, cache.VwCacheDaAccessor); return cbaHvosAffectedByEdit; }
/// <summary> /// Cache all the different types of freeform annotations for each segment in the given hvoPara. /// Stores using freeform annotations with SegmentFreeformAnnotationsFlid. /// Specifically, after calling this, /// - for each segment in hvoPara.Segments, property SegmentFreeformAnnotationsFlid(cache) is set /// to a list of all the indirect annotations which applyTo that segment and which are of /// type literal translation, free translation,or note /// - for each such indirect annotation, its type is cached, and also its Comment in all the /// specified writing systems. /// </summary> /// <param name="cache"></param> /// <param name="hvoPara"></param> /// <param name="wsIds"></param> public static void LoadSegmentFreeformAnnotationData(FdoCache cache, int hvoPara, Set<int> wsIds) { int[] segIds = cache.GetVectorProperty(hvoPara, SegmentsFlid(cache), true); string whereStmt = String.Format("where cts.BeginObject = {0}", hvoPara); string orderByStmt = "order by cts.BeginOffset, cts.id, ca.AnnotationType, ca.id"; LoadSegmentFreeformAnnotationData(cache, whereStmt, orderByStmt, segIds, wsIds.ToArray()); }
/// <summary> /// Load the information we need to display a paragraph of free (back) translations: for each paragraph /// load its segments, for each segment load the free translation. We assume the segments /// property of each paragraph already exists, and want the BeginOffset, EndOffset, BeginObject, and Free Translation /// properties of each segment, and the Comment of the FT. /// Also ensures all the segments are real and have an FT annotation. /// </summary> /// <param name="paragraphs"></param> /// <param name="cache"></param> /// <param name="ws"></param> public static void LoadSegmentFreeTranslations(int[] paragraphs, FdoCache cache, int ws) { int kflidSegments = SegmentsFlid(cache); List<int> segments = new List<int>(); foreach (int hvoPara in paragraphs) { int[] segs = cache.GetVectorProperty(hvoPara, kflidSegments, true); int iseg = 0; foreach (int hvoSeg in segs) { int hvoRealSeg = hvoSeg; if (cache.IsDummyObject(hvoSeg)) hvoRealSeg = CmBaseAnnotation.ConvertBaseAnnotationToReal(cache, hvoSeg).Hvo; segments.Add(hvoRealSeg); segs[iseg++] = hvoRealSeg; } // Update the list. cache.VwCacheDaAccessor.CacheVecProp(hvoPara, kflidSegments, segs, segs.Length); } if (segments.Count == 0) return; // somehow we can have none, and then the query fails. int hvoFt = cache.GetIdFromGuid(LangProject.kguidAnnFreeTranslation); string ids = JoinIds(segments.ToArray(), ","); int kflidFT = SegmentFreeTranslationFlid(cache); if (cache.DatabaseAccessor != null) { string sql = @"select seg.id, seg.BeginObject, seg.BeginOffset, seg.EndOffset, ft.id, ft.class$, ft.UpdStmp, ftc.Txt, ftc.Fmt from CmBaseAnnotation seg join CmIndirectAnnotation_AppliesTo ftseg on ftseg.Dst = seg.id join CmIndirectAnnotation_ ft on ft.id = ftseg.Src and ft.AnnotationType = " + hvoFt + @" left outer join CmAnnotation_Comment ftc on ftc.Obj = ft.id and ftc.ws = " + ws + @" where seg.id in (" + ids + ")"; IDbColSpec dcs = DbColSpecClass.Create(); dcs.Push((int) DbColType.koctBaseId, 0, 0, 0); // ID (of segment) dcs.Push((int) DbColType.koctObj, 1, (int) CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginObject, 0); dcs.Push((int) DbColType.koctInt, 1, (int) CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginOffset, 0); dcs.Push((int) DbColType.koctInt, 1, (int) CmBaseAnnotation.CmBaseAnnotationTags.kflidEndOffset, 0); dcs.Push((int) DbColType.koctObj, 1, kflidFT, 0); // Free translation indirect annotation dcs.Push((int) DbColType.koctInt, 5, (int) CmObjectFields.kflidCmObject_Class, 0); // class of FT annotation dcs.Push((int) DbColType.koctTimeStamp, 5, 0, 0); // timestamp of FT annotation dcs.Push((int)DbColType.koctMlsAlt, 5, (int)CmAnnotation.CmAnnotationTags.kflidComment, ws); dcs.Push((int)DbColType.koctFmt, 5, (int)CmAnnotation.CmAnnotationTags.kflidComment, ws); cache.LoadData(sql, dcs, 0); } // Make sure each segment has a free translation. foreach (int hvoSeg in segments) { int hvoFT = cache.GetObjProperty(hvoSeg, kflidFT); if (hvoFT == 0) { ICmIndirectAnnotation ann = CmIndirectAnnotation.CreateUnownedIndirectAnnotation(cache); ann.AppliesToRS.Append(hvoSeg); ann.AnnotationTypeRAHvo = hvoFt; cache.VwCacheDaAccessor.CacheObjProp(hvoSeg, kflidFT, ann.Hvo); } } }
/// <summary> /// Return the segment range in terms of the segment indexes of the BeginObject segment property of the given hvoCba. /// </summary> /// <param name="cache"></param> /// <param name="hvoCba"></param> /// <param name="iBeginSegment">zero-based index into segments</param> /// <param name="iEndSegment">zero-based into segments</param> /// <returns></returns> static public bool TryGetSegmentRange(FdoCache cache, int hvoCba, out int iBeginSegment, out int iEndSegment) { iBeginSegment = -1; iEndSegment = -1; int[] segments = null; // if it's a twfic type, then use twfic info, otherwise find a segment range. ICmBaseAnnotation cba = CmBaseAnnotation.CreateFromDBObject(cache, hvoCba); int hvoPara = cba.BeginObjectRAHvo; IVwVirtualHandler vh; // first try to get the segments from our Segments virtual handler // if that has not been loaded for the paragraph, try SegmentsIgnoreTwfics // to save time. if (cache.TryGetVirtualHandler(StTxtPara.SegmentsFlid(cache), out vh) && (vh as BaseFDOPropertyVirtualHandler).IsPropInCache(cache.MainCacheAccessor, hvoPara, 0)) { if (cba.AnnotationTypeRAHvo != 0) { StTxtPara.TwficInfo twficInfo = new StTxtPara.TwficInfo(cache, hvoCba); if (twficInfo.SegmentIndex >= 0) { iBeginSegment = twficInfo.SegmentIndex; // return zero-based index. } else if (!cache.IsDummyObject(hvoCba)) { int segIndexLogical; string sql = string.Format("exec GetSegmentIndex {0}, {1}", hvoCba, CmAnnotationDefn.TextSegment(cache).Hvo); DbOps.ReadOneIntFromCommand(cache, sql, null, out segIndexLogical); if (segIndexLogical > 0) iBeginSegment = segIndexLogical - 1; // subtract 1 to get a zero-based index. } } if (iBeginSegment < 0) segments = cache.GetVectorProperty(hvoPara, vh.Tag, true); } else if (cache.TryGetVirtualHandler(StTxtPara.SegmentsIgnoreTwficsFlid(cache), out vh)) { segments = cache.GetVectorProperty(hvoPara, vh.Tag, true); } if (iBeginSegment < 0) { // this is annotation into a paragraph (but may not be a twfic or exist in SegForms). // if it's not a twfic, find a segment range. ISilDataAccess sda = cache.MainCacheAccessor; int ihvoSeg = 0; int cbaBeginOffset = cba.BeginOffset; int cbaEndOffset = cba.EndOffset; for (; ihvoSeg < segments.Length; ihvoSeg++) { int segEndOffset = sda.get_IntProp(segments[ihvoSeg], (int)CmBaseAnnotation.CmBaseAnnotationTags.kflidEndOffset); if (segEndOffset <= cbaBeginOffset) { continue; } else if (iBeginSegment < 0) { iBeginSegment = ihvoSeg; } if (segEndOffset > cbaEndOffset) { iEndSegment = ihvoSeg; break; // we've passed our annotation's EndOffset, so the previous segment is the last one in range. } } // ihvoSeg should now be one index passed the segment in our range. this eguals the logical segment number. if (iBeginSegment >= 0 && iEndSegment == -1) { iEndSegment = ihvoSeg < segments.Length ? ihvoSeg - 1 : segments.Length - 1; } } return iBeginSegment >= 0; }
/// <summary> /// Find a dummy segment wordform annotation, and replace with a real annotation it in the cache. /// </summary> /// <param name="cache"></param> /// <param name="hvoOldAnnotation"></param> /// <param name="hvoNewAnnotation"></param> /// <returns>if nonzero, this will be inserted in place of the old one. /// if zero, we'll simply delete the old one.</returns> internal static void CacheReplaceTWFICAnnotation(FdoCache cache, int hvoOldAnnotation, int hvoNewAnnotation) { int ktagSegmentForms = CmBaseAnnotation.SegmentFormsFlid(cache); int kflidOccurrences = WfiWordform.OccurrencesFlid(cache); ISilDataAccess sda = cache.MainCacheAccessor; int hvoParaSeg = 0; int iParaSeg = -1; bool fIsFirstTwfic = false; int iSegForm = StTxtPara.TwficSegmentLocation(cache, hvoOldAnnotation, out hvoParaSeg, out iParaSeg, out fIsFirstTwfic); IVwCacheDa cda = cache.VwCacheDaAccessor; int[] newItems = hvoNewAnnotation != 0 ? new int[] { hvoNewAnnotation } : new int[0]; if (hvoParaSeg != 0 && iSegForm >= 0) { CacheReplaceOneUndoAction cacheReplaceSegmentFormAction = new CacheReplaceOneUndoAction(cache, hvoParaSeg, ktagSegmentForms, iSegForm, iSegForm + 1, newItems); cacheReplaceSegmentFormAction.DoIt(); if (cache.ActionHandlerAccessor != null) { cache.ActionHandlerAccessor.AddAction(cacheReplaceSegmentFormAction); } } int hvoOldWordform = 0; if (WfiWordform.TryGetWfiWordformFromInstanceOf(cache, hvoOldAnnotation, out hvoOldWordform)) { // replace the dummy annotation on its wordform, if we haven't already. List<int> dummyAnnotations = new List<int>(cache.GetVectorProperty(hvoOldWordform, kflidOccurrences, true)); int iAnn = dummyAnnotations.IndexOf(hvoOldAnnotation); if (iAnn >= 0) { CacheReplaceOneUndoAction cacheReplaceOccurrenceAction = new CacheReplaceOneUndoAction(cache, hvoOldWordform, kflidOccurrences, iAnn, iAnn + 1, newItems); cacheReplaceOccurrenceAction.DoIt(); if (cache.ActionHandlerAccessor != null) { cache.ActionHandlerAccessor.AddAction(cacheReplaceOccurrenceAction); } } } // try converting the owning segment to real, if we're converting the twfic to real. if (hvoOldAnnotation != 0 && hvoNewAnnotation != 0 && cache.IsDummyObject(hvoOldAnnotation) && !cache.IsDummyObject(hvoNewAnnotation) && cache.IsDummyObject(hvoParaSeg)) { hvoParaSeg = CmBaseAnnotation.ConvertBaseAnnotationToReal(cache, hvoParaSeg).Hvo; } }
/// <summary> /// Find a dummy paragraph segment annotation and replace it with a real annotation in the cache. /// </summary> /// <param name="cache"></param> /// <param name="hvoOldAnnotation"></param> /// <param name="hvoNewAnnotation">if nonzero, this will be inserted in place of the old one. /// if zero, we'll simply delete the old one.</param> internal static void CacheReplaceTextSegmentAnnotation(FdoCache cache, int hvoOldAnnotation, int hvoNewAnnotation) { int kflidParaSegments = StTxtPara.SegmentsFlid(cache); int ktagSegmentForms = CmBaseAnnotation.SegmentFormsFlid(cache); ISilDataAccess sda = cache.MainCacheAccessor; IVwCacheDa cda = cache.VwCacheDaAccessor; // find the paraSegment for the old annotation int hvoPara = sda.get_ObjectProp(hvoOldAnnotation, (int)CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginObject); List<int> paraSegments = new List<int>(cache.GetVectorProperty(hvoPara, kflidParaSegments, true)); int iParaSeg = paraSegments.IndexOf(hvoOldAnnotation); Debug.Assert(iParaSeg != -1); if (iParaSeg >= 0) { int[] segmentForms = cache.GetVectorProperty(hvoOldAnnotation, ktagSegmentForms, true); if (hvoNewAnnotation != 0) { // first, transfer the old annotation's WordformSegments vector. cda.CacheVecProp(hvoNewAnnotation, ktagSegmentForms, segmentForms, segmentForms.Length); } int[] newItems = hvoNewAnnotation != 0 ? new int[] { hvoNewAnnotation } : new int[0]; // now, replace the old paraSegment with the new. CacheReplaceOneUndoAction cacheReplaceParaSegmentAction = new CacheReplaceOneUndoAction( cache, hvoPara, kflidParaSegments, iParaSeg, iParaSeg + 1, newItems); cacheReplaceParaSegmentAction.DoIt(); if (cache.ActionHandlerAccessor != null) { cache.ActionHandlerAccessor.AddAction(cacheReplaceParaSegmentAction); } } }
/// <summary> /// Return the hvo for theCmBaseAnnotation that /// matches the given boundaries in an StTxtPara object. /// If no exact match is found, return the nearest segment (preferably the following word). /// </summary> /// <param name="hvoStTxtPara"></param> /// <param name="ichMin"></param> /// <param name="ichLim"></param> /// <param name="fOnlyTWFIC">true, if restricted to TWFIC</param> /// <param name="fExactMatch"> true if we return an exact match, false otherwise.</param> /// <returns>hvo is 0 if not found.</returns> static internal int FindAnnotationHvoForStTxtPara(FdoCache cache, int hvoStTxtPara, int ichMin, int ichLim, bool fOnlyTWFIC, out bool fExactMatch) { int twficType = CmAnnotationDefn.Twfic(cache).Hvo; int textSegType = CmAnnotationDefn.TextSegment(cache).Hvo; fExactMatch = false; int clsid = cache.GetClassOfObject(hvoStTxtPara); if (clsid != StTxtPara.kClassId) { Debug.Assert(clsid != StTxtPara.kClassId, "hvoStTxtPara should be of class StTxtPara."); return 0; } int kflidParaSegment = InterlinVc.ParaSegmentTag(cache); ISilDataAccess sda = cache.MainCacheAccessor; // first find the closest segment. int[] segments = cache.GetVectorProperty(hvoStTxtPara, kflidParaSegment, true); ICmBaseAnnotation cbaClosestSeg = FindClosestAnnotation(cache, segments, textSegType, ichMin, ichLim, out fExactMatch); if (cbaClosestSeg == null) return 0; // if it was an exact match for a segment, return it. if (cbaClosestSeg != null && fExactMatch && !fOnlyTWFIC) return cbaClosestSeg.Hvo; // otherwise, see if we can find a closer wordform int[] segmentForms = cache.GetVectorProperty(cbaClosestSeg.Hvo, InterlinVc.SegmentFormsTag(cache), true); ICmBaseAnnotation cbaClosestWf = FindClosestAnnotation(cache, segmentForms, twficType, ichMin, ichLim, out fExactMatch); if (cbaClosestWf == null) { return fOnlyTWFIC ? 0 : cbaClosestSeg.Hvo; } return cbaClosestWf.Hvo; }
/// <summary> /// Bring up a chooser for selecting a natural class, and insert it into the string /// representation stored in the rootbox. This static method is used by /// SIL.FieldWorks.Common.Framework.DetailControls.PhoneEnvReferenceSlice and /// SIL.FieldWorks.XWorks.MorphologyEditor.PhEnvStrRepresentationSlice. /// </summary> /// <param name="rootb"></param> /// <param name="cache"></param> /// <param name="persistenceProvider"></param> /// <param name="mediator"></param> /// <returns></returns> public static bool ChooseNaturalClass(IVwRootBox rootb, FdoCache cache, IPersistenceProvider persistenceProvider, XCore.Mediator mediator) { List<int> candidates = null; int hvoPhonData = cache.LangProject.PhonologicalDataOA.Hvo; int flidNatClasses = (int)PhPhonData.PhPhonDataTags.kflidNaturalClasses; int[] targetHvos = cache.GetVectorProperty(hvoPhonData, flidNatClasses, false); if (targetHvos.Length > 0) candidates = new List<int>(targetHvos); else candidates = new List<int>(0); ObjectLabelCollection labels = new ObjectLabelCollection(cache, candidates, "", cache.LanguageWritingSystemFactoryAccessor.GetStrFromWs(cache.DefaultAnalWs)); using (ReallySimpleListChooser chooser = new ReallySimpleListChooser(persistenceProvider, labels, "NaturalClass")) { string sTitle = null; string sDescription = null; string sJumpLabel = null; if (mediator != null && mediator.HasStringTable) { sTitle = mediator.StringTbl.GetString("kstidChooseNaturalClass", "Linguistics/Morphology/NaturalClassChooser"); sDescription = mediator.StringTbl.GetString("kstidNaturalClassListing", "Linguistics/Morphology/NaturalClassChooser"); sJumpLabel = mediator.StringTbl.GetString("kstidGotoNaturalClassList", "Linguistics/Morphology/NaturalClassChooser"); } if (sTitle == null || sTitle.Length == 0 || sTitle == "kstidChooseNaturalClass") sTitle = XMLViewsStrings.ksChooseNaturalClass; if (sDescription == null || sDescription.Length == 0 || sDescription == "kstidNaturalClassListing") sDescription = XMLViewsStrings.ksNaturalClassDesc; if (sJumpLabel == null || sJumpLabel.Length == 0 || sJumpLabel == "kstidGotoNaturalClassList") sJumpLabel = XMLViewsStrings.ksEditNaturalClasses; chooser.Cache = cache; chooser.SetObjectAndFlid(0, 0); chooser.InitializeRaw(mediator, sTitle, sDescription, sJumpLabel, "naturalClassedit", "analysis vernacular"); System.Windows.Forms.DialogResult res = chooser.ShowDialog(); if (System.Windows.Forms.DialogResult.Cancel == res) return true; if (chooser.HandleAnyJump()) return true; if (chooser.ChosenOne != null) { int hvo = chooser.ChosenOne.Hvo; IPhNaturalClass pnc = PhNaturalClass.CreateFromDBObject(cache, hvo); ITsString tss = pnc.Abbreviation.BestAnalysisVernacularAlternative; string sName = tss.Text; string sIns = String.Format("[{0}]", sName); int wsPending = cache.DefaultVernWs; IVwRootSite site = rootb.Site; IVwGraphics vg = null; if (site != null) vg = site.get_ScreenGraphics(rootb); rootb.OnTyping(vg, sIns, 0, 0, '[', ref wsPending); } } return true; }