/// <summary> /// Register initial state information that is expected to change during the life of the helper. /// </summary> /// <param name="hvoParasAffected"></param> public void CaptureInitialStateInfo(int hvoCurrentAnnotation) { m_hvoCurrentAnnotation = hvoCurrentAnnotation; ICmBaseAnnotation currentAnnotation = new CmBaseAnnotation(m_cache, hvoCurrentAnnotation); m_para = currentAnnotation.BeginObjectRA as StTxtPara; }
public void AnnotationStringValue() { // Use old-style creation to support in-memory testing; cf CmBaseAnnotation.CreateUnownedCba. CmBaseAnnotation ann = new CmBaseAnnotation(); Cache.LangProject.AnnotationsOC.Add(ann); ann.BeginOffset = 4; ann.EndOffset = 10; // The below is a non-standard usage of the TextOA field. It works for this test as a place // to store the text we're testing, but normally it's purpose is for a (possibly) multi-paragraph // commentary on the target of the annotation (pointed to by BeginObject). This would be similar to // how a ScriptureNote.Discussion points to a JournalText (subclass of StText). ann.TextOA = new StText(); StTxtPara para = new StTxtPara(); ann.TextOA.ParagraphsOS.Append(para); para.Contents.Text = "pus yalola nihimbilira. nihimbilira pus yalola. hesyla nihimbilira."; ann.BeginObjectRA = para; ann.EndObjectRA = para; ann.Flid = (int)StTxtPara.StTxtParaTags.kflidContents; // Install the virtual property and get its id. int flid = CmBaseAnnotation.StringValuePropId(Cache); // The text of the annotation should be 'yalola'. Assert.AreEqual("yalola", Cache.MainCacheAccessor.get_StringProp(ann.Hvo, flid).Text, "Wrong StringValue for 'yalola' annotation"); }
/// <summary> /// Verify that the paragraph has the expected number of segments with the expected free translations. /// Lengths should be the lengths of the segments. /// </summary> private void VerifySegments(StTxtPara para, string[] freeTranslations, int[] lengths, string label) { int cseg = Cache.GetVectorSize(para.Hvo, kflidSegments); Assert.AreEqual(freeTranslations.Length, cseg); int i = 0; int cumLength = 0; foreach (string ft in freeTranslations) { int hvoSeg = Cache.GetVectorItem(para.Hvo, kflidSegments, i); CmBaseAnnotation seg = new CmBaseAnnotation(Cache, hvoSeg); Assert.AreEqual(cumLength, seg.BeginOffset, label + " - beginOffset " + i); cumLength += lengths[i]; Assert.AreEqual(cumLength, seg.EndOffset, label + " - endOffset " + i); Assert.AreEqual(m_hvoSegAnnDefn, seg.AnnotationTypeRAHvo, label + " - seg ann type " + i); if (ft != null) { int hvoFt = Cache.GetObjProperty(hvoSeg, kflidFT); Assert.IsTrue(hvoFt != 0, label + "ft present " + i); CmIndirectAnnotation ftAnn = new CmIndirectAnnotation(Cache, hvoFt); Assert.AreEqual(ft, ftAnn.Comment.AnalysisDefaultWritingSystem.Text, label + " - comment " + i); Assert.AreEqual(m_hvoFtAnnDefn, ftAnn.AnnotationTypeRAHvo, label + " - ft type " + i); Assert.AreEqual(1, ftAnn.AppliesToRS.Count, label + " - appliesTo length " + i); Assert.AreEqual(seg.Hvo, ftAnn.AppliesToRS.HvoArray[0], label + " - applies to val " + i); } i++; } }
private bool DeleteFreeform(IVwSelection sel) { int hvoAnnotation; if (!CanDeleteFF(sel, out hvoAnnotation)) return false; int hvoSeg, tagFF, ihvoFF, cpropPrevious; IVwPropertyStore vps; // NOTE: Do not use ihvoFF for updating the cache directly, because the display vector indices // does not necessarily correspond to the cache vector indices. sel.PropInfo(false, 1, out hvoSeg, out tagFF, out ihvoFF, out cpropPrevious, out vps); CmBaseAnnotation seg = new CmBaseAnnotation(Cache, hvoSeg); CmIndirectAnnotation ft = new CmIndirectAnnotation(Cache, hvoAnnotation); bool wasFt = ft.AnnotationTypeRAHvo == Cache.GetIdFromGuid(LangProject.kguidAnnFreeTranslation); StTxtPara para = seg.BeginObjectRA as StTxtPara; m_fdoCache.DeleteObject(hvoAnnotation); m_fdoCache.PropChanged(null, PropChangeType.kpctNotifyAll, hvoSeg, tagFF, ihvoFF, 0, 1); if (wasFt && para != null) FreeTransEditMonitor.UpdateMainTransFromSegmented(para, Cache.LangProject.CurAnalysisWssRS.HvoArray); return true; // handled }
/// <summary> /// Copies out the cba info in the paragraph definition cba node into a new real cba. /// </summary> /// <param name="iSegment"></param> /// <param name="iSegForm"></param> /// <returns></returns> internal int ExportCbaNodeToReal(int iSegment, int iSegForm) { int hvoSegFormInParaDef = GetExpectedSegmentForm(iSegment, iSegForm); ICmBaseAnnotation cbaInParaDef = new CmBaseAnnotation(m_cache, hvoSegFormInParaDef); ICmBaseAnnotation exportedCba = CmBaseAnnotation.CreateRealAnnotation(m_cache, cbaInParaDef.AnnotationTypeRAHvo, cbaInParaDef.InstanceOfRAHvo, cbaInParaDef.BeginObjectRAHvo, cbaInParaDef.Flid, cbaInParaDef.BeginOffset, cbaInParaDef.EndOffset); return exportedCba.Hvo; }
private void AddSegment(StTxtPara para, int ichMin, int ichLim, string ft) { // Since this is an in-memory test, we can't use CmBaseAnnotation.CreateUnownedCba. CmBaseAnnotation seg = new CmBaseAnnotation(); Cache.LangProject.AnnotationsOC.Add(seg); seg.AnnotationTypeRAHvo = m_hvoSegAnnDefn; seg.BeginOffset = ichMin; seg.EndOffset = ichLim; seg.BeginObjectRA = para; seg.EndObjectRA = para; if (Cache.MainCacheAccessor.get_IsPropInCache(para.Hvo, kflidSegments, (int)CellarModuleDefns.kcptReferenceSequence, 0)) { int cseg = Cache.GetVectorSize(para.Hvo, kflidSegments); m_scrInMemoryCache.CacheAccessor.CacheReplace(para.Hvo, kflidSegments, cseg, cseg, new int[] {seg.Hvo}, 1); } else { // Don't want to just read it, because that actually parses the paragraph. If it's not already in memory // this is the first one, so just make it so. Cache.VwCacheDaAccessor.CacheVecProp(para.Hvo, kflidSegments, new int[] {seg.Hvo}, 1); } if (ft != null) { // Since this is an in-memory test, we can't use CmIndirectAnnotation.CreateUnownedIndirectAnnotation. CmIndirectAnnotation ftAnn = new CmIndirectAnnotation(); Cache.LangProject.AnnotationsOC.Add(ftAnn); ftAnn.AnnotationTypeRAHvo = m_hvoFtAnnDefn; ftAnn.AppliesToRS.Append(seg); ftAnn.Comment.SetAlternative(ft, Cache.DefaultAnalWs); m_scrInMemoryCache.CacheAccessor.CacheObjProp(seg.Hvo, kflidFT, ftAnn.Hvo); } }
private void ValidateGuesses(List<int> expectedGuesses, StTxtPara paraWithGuesses) { List<int> segsParaGuesses = paraWithGuesses.Segments; int iExpectedGuess = 0; foreach (int hvoSegParaGuesses in segsParaGuesses) { List<int> segFormsParaGuesses = paraWithGuesses.SegmentForms(hvoSegParaGuesses); Assert.AreEqual(expectedGuesses.Count, segFormsParaGuesses.Count); foreach (int hvoSegFormParaGuesses in segFormsParaGuesses) { int hvoGuessActual = 0; CmBaseAnnotation cba = new CmBaseAnnotation(Cache, hvoSegFormParaGuesses); if (cba.InstanceOfRAHvo != 0) { // should be a twfic so get it's guess. StTxtPara.TwficInfo cbaInfo = new StTxtPara.TwficInfo(Cache, cba.Hvo); hvoGuessActual = cbaInfo.GetGuess(); } Assert.AreEqual(expectedGuesses[iExpectedGuess], hvoGuessActual, "Guess mismatch"); iExpectedGuess++; } } }
/// <summary> /// Get the segments of the paragraph. This is public static to allow others to use /// the same code. This will actually parse the text of the paragraph, create any /// segments that do not yet exist, and create any needed free translation annotations /// to go with them. It also sets the kflidSegments (virtual) property of the paragraph, /// and the kflidFT (virtual) property of the segments. /// </summary> /// <returns>array of ICmBaseAnnotation objects for the segments</returns> public static ICmBaseAnnotation[] GetMainParaSegments(IStTxtPara para, int wsBt, out int[] paraSegs) { FdoCache cache = EnsureMainParaSegments(para, wsBt); int kflidSegments = StTxtPara.SegmentsFlid(cache); paraSegs = cache.GetVectorProperty(para.Hvo, kflidSegments, true); ICmBaseAnnotation[] segments = new ICmBaseAnnotation[paraSegs.Length]; for (int i = 0; i < paraSegs.Length; i++) { // This prevents trying to really load it from the database, which is typically not // useful and actully causes failures of some tests when using a memory cache that considers all // objects to be non-dummies. cache.VwCacheDaAccessor.CacheIntProp(paraSegs[i], (int)CmObjectFields.kflidCmObject_Class, (int)CmBaseAnnotation.kclsidCmBaseAnnotation); segments[i] = new CmBaseAnnotation(cache, paraSegs[i]); } return segments; }
/// <summary> /// /// </summary> /// <param name="realParagraphAnnotations"></param> /// <param name="unusedAnnotations"></param> /// <param name="ichMin">begin offset in actual text</param> /// <param name="ichLim">end offset in actual text</param> /// <param name="cbaFirstUnused">the first unused cba, whether or not we could reuse it.</param> /// <returns>true if we reused it.</returns> protected bool TryReuseFirstUnusedCbaMatchingText(Dictionary<int, List<int>> realParagraphAnnotations, Set<int> unusedAnnotations, int ichMin, int ichLim, out CmBaseAnnotation cbaFirstUnused, out List<int> annotations, out int iann) { cbaFirstUnused = null; annotations = null; iann = -1; if (realParagraphAnnotations.TryGetValue(m_para.Hvo, out annotations)) { iann = IndexOfFirstUnusedId(annotations); if (iann >= annotations.Count) return false; // we need to assume everything we will be accessing has already been cached // NOTE: for performance purposes, class id has not been cached, so we need to explicitly // tell the CmObject constructor not to validate or load data for this object, otherwise // otherwise it will try to load data for each annotation, and that takes too much time! (LT-8038) cbaFirstUnused = new CmBaseAnnotation(m_cache, annotations[iann], false, false); if (cbaFirstUnused.BeginOffset == ichMin && cbaFirstUnused.EndOffset == ichLim) { // Reuse this annotation UseId(iann, annotations, unusedAnnotations); return true; } } return false; }
public void LT7974_Phrase_MakeAndBreak() { CheckDisposed(); // 1. Make Phrases IList<int[]> secondaryPathsToJoinWords = new List<int[]>(); IList<int[]> secondaryPathsToBreakPhrases = new List<int[]>(); ParagraphBuilder pb = new ParagraphBuilder(m_textsDefn, m_text1, (int)Text1ParaIndex.PhraseWordforms); ParagraphAnnotatorForParagraphBuilder tapb = new ParagraphAnnotatorForParagraphBuilder(pb); // go ahead and parse the text generating real wordforms to be more like a real user situation (LT-7974) // and reset the concordance to simulate the situation where the user hasn't loaded ConcordanceWords yet. (Cache.LangProject.WordformInventoryOA as WordformInventory).ResetConcordanceWordformsAndOccurrences(); bool fDidParse; (m_text1.ContentsOA as StText).LastParsedTimestamp = 0; ParagraphParser.ParseText(m_text1.ContentsOA, new NullProgressState(), out fDidParse); pb.ResyncExpectedAnnotationIds(); // first do a basic phrase (without secondary phrases (guesses)), which should not delete "xxxpus" or "xxxyalola" // since they occur later in the text. // [xxxpus xxxyalola] xxxnihimbilira. xxxpus xxxyalola xxxhesyla xxxnihimbilira. xxxpus xxxyalola xxxnihimbilira int hvoCba1_0 = tapb.GetSegmentForm(1, 0); // second xxxpus int hvoCba1_1 = tapb.GetSegmentForm(1, 1); // second xxxyalola ICmBaseAnnotation cba1_0 = new CmBaseAnnotation(Cache, hvoCba1_0); ICmBaseAnnotation cba1_1 = new CmBaseAnnotation(Cache, hvoCba1_1); IWfiWordform wf1 = cba1_0.InstanceOfRA as WfiWordform; IWfiWordform wf2 = cba1_0.InstanceOfRA as WfiWordform; tapb.MergeAdjacentAnnotations(0, 0, secondaryPathsToJoinWords, secondaryPathsToBreakPhrases); // after the merge, make sure the wordforms for xxxpus and xxxyalola are still valid Assert.IsTrue(wf1.IsValidObject(), "expected xxxpus to still be valid"); Assert.IsTrue(wf2.IsValidObject(), "expected xxxyalola to still be valid"); tapb.ValidateAnnotations(true); // now break the phrase and make sure we delete this wordform, b/c it is not occurring elsewhere (Cache.LangProject.WordformInventoryOA as WordformInventory).ResetConcordanceWordformsAndOccurrences(); pb.ResyncExpectedAnnotationIds(); // \xxxpus\ \xxxyalola\ xxxnihimbilira. xxxpus xxxyalola xxxhesyla xxxnihimbilira. xxxpus xxxyalola xxxnihimbilira int hvoCba0_0 = tapb.GetSegmentForm(0, 0); // xxxpus xxxyalola ICmBaseAnnotation cba0_0 = new CmBaseAnnotation(Cache, hvoCba0_0); IWfiWordform wf3 = cba0_0.InstanceOfRA as WfiWordform; secondaryPathsToJoinWords.Clear(); secondaryPathsToBreakPhrases.Clear(); tapb.BreakPhrase(0, 0, secondaryPathsToBreakPhrases, secondaryPathsToJoinWords, null); Assert.IsFalse(wf3.IsValidObject(), "expected 'xxxpus xxxyalola' to be deleted."); tapb.ValidateAnnotations(true); // rejoin the first phrase, parse the text, and break the first phrase // [xxxpus xxxyalola] xxxnihimbilira. {xxxpus xxxyalola} xxxhesyla xxxnihimbilira. {xxxpus xxxyalola} xxxnihimbilira secondaryPathsToJoinWords.Add(new int[2] { 1, 0 }); // {xxxpus xxxyalola} xxxhesyla secondaryPathsToJoinWords.Add(new int[2] { 2, 0 }); // {xxxpus xxxyalola} xxxnihimbilira tapb.MergeAdjacentAnnotations(0, 0, secondaryPathsToJoinWords, secondaryPathsToBreakPhrases); hvoCba0_0 = tapb.GetSegmentForm(0, 0); // xxxpus xxxyalola cba0_0 = new CmBaseAnnotation(Cache, hvoCba0_0); wf1 = cba0_0.InstanceOfRA as WfiWordform; tapb.ReparseParagraph(); // just break the new phrase (and the leave existing guesses) // \xxxpus\ \xxxyalola\ xxxnihimbilira. {xxxpus xxxyalola} xxxhesyla xxxnihimbilira. {xxxpus xxxyalola} xxxnihimbilira (Cache.LangProject.WordformInventoryOA as WordformInventory).ResetConcordanceWordformsAndOccurrences(); secondaryPathsToJoinWords.Clear(); tapb.BreakPhrase(0, 0, secondaryPathsToBreakPhrases, secondaryPathsToJoinWords, null); Assert.IsTrue(wf1.IsValidObject(), "expected 'xxxpus xxxyalola' to still be valid"); tapb.ValidateAnnotations(true); // xxxpus xxxyalola xxxnihimbilira. \xxxpus\ \xxxyalola\ xxxhesyla xxxnihimbilira. {xxxpus xxxyalola} xxxnihimbilira tapb.BreakPhrase(1, 0, secondaryPathsToBreakPhrases, secondaryPathsToJoinWords, null); Assert.IsTrue(wf1.IsValidObject(), "expected 'xxxpus xxxyalola' to still be valid"); tapb.ValidateAnnotations(true); // xxxpus xxxyalola xxxnihimbilira. xxxpus xxxyalola xxxhesyla xxxnihimbilira. \xxxpus\ \xxxyalola\ xxxnihimbilira tapb.BreakPhrase(2, 0, secondaryPathsToBreakPhrases, secondaryPathsToJoinWords, null); Assert.IsFalse(wf1.IsValidObject(), "expected 'xxxpus xxxyalola' to be deleted"); tapb.ValidateAnnotations(true); // now do two joins, the second resulting in deletion of a wordform. // xxxpus xxxyalola xxxnihimbilira. xxxpus [xxxyalola xxxhesyla] xxxnihimbilira. xxxpus xxxyalola xxxnihimbilira // xxxpus xxxyalola xxxnihimbilira. xxxpus [xxxyalola xxxhesyla xxxnihimbilira]. xxxpus xxxyalola xxxnihimbilira (Cache.LangProject.WordformInventoryOA as WordformInventory).ResetConcordanceWordformsAndOccurrences(); (m_text1.ContentsOA as StText).LastParsedTimestamp = 0; ParagraphParser.ParseText(m_text1.ContentsOA, new NullProgressState(), out fDidParse); pb.ResyncExpectedAnnotationIds(); tapb.MergeAdjacentAnnotations(1, 1, secondaryPathsToJoinWords, secondaryPathsToBreakPhrases); hvoCba1_1 = tapb.GetSegmentForm(1, 1); // xxxyalola xxxhesyla cba1_1 = new CmBaseAnnotation(Cache, hvoCba1_1); IWfiWordform wf4 = cba1_1.InstanceOfRA as WfiWordform; tapb.MergeAdjacentAnnotations(1, 1, secondaryPathsToJoinWords, secondaryPathsToBreakPhrases); // this merge should have deleted 'xxxyalola xxxhesyla' Assert.IsFalse(wf4.IsValidObject(), "expected 'xxxyalola xxxhesyla' to be deleted."); tapb.ValidateAnnotations(true); }
/// <summary> /// Given that segment is a 'label' segment (typically an embedded identifying number), /// figure out what to display as the corresponding label in a back translation view. /// This is made separate so that TeStVc can override to use a different numbering scheme /// in the BT. /// </summary> /// <param name="segment"></param> /// <returns></returns> protected override ITsString GetBackTransLabelText(CmBaseAnnotation segment) { ITsString tssLabel = segment.TextAnnotated; if (tssLabel == null) return null; IScripture scr = segment.Cache.LangProject.TranslatedScriptureOA; return scr.ConvertCVNumbersInStringForBT(tssLabel, BackTranslationWS); }
/// <summary> /// Given that segment is a 'label' segment (typically an embedded identifying number), /// figure out what to display as the corresponding label in a back translation view. /// This is made separate so that TeStVc can override to use a different numbering scheme /// in the BT. /// </summary> /// <param name="segment"></param> /// <returns></returns> protected virtual ITsString GetBackTransLabelText(CmBaseAnnotation segment) { return segment.TextAnnotated; }
// Make some sort of wfics for the text of the specified paragraph. Assumes no double spaces! // Caches results and does not repeat on same para internal int[] MakeAnnotations(StTxtPara para) { int[] previous; if (m_annotations.TryGetValue(para.Hvo, out previous)) return previous; string contents = para.Contents.Text; string[] words = contents.Split(new char[] { ' ', '.' }); int ich = 0; List<int> results = new List<int>(); ICmAnnotationDefn WficType = CmAnnotationDefn.Twfic(Cache); foreach (string word in words) { if (word == "") { ich++; continue; } WfiWordform wordform = new WfiWordform(); Cache.LangProject.WordformInventoryOA.WordformsOC.Add(wordform); wordform.Form.SetAlternative(word, Cache.DefaultVernWs); // JohnT: This should ideally use CmBaseAnnotation.CreateUnownedCba. But most or all uses of this // method are memory-only tests, and that method requires a database. CmBaseAnnotation cba = new CmBaseAnnotation(); Cache.LangProject.AnnotationsOC.Add(cba); cba.BeginOffset = ich; ich += word.Length; cba.EndOffset = ich; ich++; // past space or dot cba.BeginObjectRA = para; cba.AnnotationTypeRA = WficType; //cba.AnnotationTypeRA = ?? can we get CmAnnotationDefn.Twfic(Cache) with a non-database cache? WfiAnalysis analysis = new WfiAnalysis(); wordform.AnalysesOC.Add(analysis); WfiGloss gloss = new WfiGloss(); analysis.MeaningsOC.Add(gloss); gloss.Form.SetAlternative(word + "Gloss" + ich, Cache.DefaultAnalWs); cba.InstanceOfRA = gloss; results.Add(cba.Hvo); } int[] result = results.ToArray(); m_annotations[para.Hvo] = result; return result; }
private void VerifySegment(int hvoSeg, int beginOffset, int endOffset, int hvoPara, string label) { CmBaseAnnotation cba = new CmBaseAnnotation(Cache, hvoSeg); Assert.AreEqual(beginOffset, cba.BeginOffset, label + " - begin"); Assert.AreEqual(endOffset, cba.EndOffset, label + " - end"); Assert.AreEqual(hvoPara, cba.BeginObjectRAHvo, label + " - para"); }
/// <summary> /// Walk through the paragraph and create word glosses (formatted: wordform.segNum.segFormNum) and segment annotations. /// </summary> /// <returns>list of wordglosses for each form in the paragraph, including non-twfics (ie. hvo == 0).</returns> internal protected virtual List<int> SetupDefaultWordGlosses() { int kAnnTypeTwfic = CmAnnotationDefn.Twfic(m_cache).Hvo; int kAnnTypePunc = CmAnnotationDefn.Punctuation(m_cache).Hvo; int iseg = 0; List<int> wordGlosses = new List<int>(); List<int> segsPara = m_para.Segments; foreach (int hvoSegPara in segsPara) { int isegform = 0; List<int> segFormsPara = m_para.SegmentForms(hvoSegPara); foreach (int hvoSegFormPara in segFormsPara) { int hvoWordGloss = 0; CmBaseAnnotation cba = new CmBaseAnnotation(m_cache, hvoSegFormPara); if (cba.AnnotationTypeRAHvo == kAnnTypeTwfic) { string twficGloss; hvoWordGloss = SetDefaultWordGloss(iseg, isegform, out twficGloss); } wordGlosses.Add(hvoWordGloss); isegform++; } // create freeform annotations for each of the segments // TODO: multiple writing systems. ITsString tssComment; SetDefaultFreeformAnnotation(iseg, LangProject.kguidAnnFreeTranslation, out tssComment); SetDefaultFreeformAnnotation(iseg, LangProject.kguidAnnLiteralTranslation, out tssComment); SetDefaultFreeformAnnotation(iseg, LangProject.kguidAnnNote.ToString(), out tssComment); iseg++; } return wordGlosses; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Common utility for the CurrentRef* properties /// </summary> /// <param name="selection"></param> /// <param name="selLimit">The limit of the selection (anchor, end, etc.) to get the /// reference of</param> /// <returns>the start and end reference of the given selection, as an array of two /// ScrReference objects</returns> /// ------------------------------------------------------------------------------------ protected virtual ScrReference[] GetCurrentRefRange(SelectionHelper selection, SelectionHelper.SelLimitType selLimit) { if (m_cache == null || selection == null || BookFilter == null) return new ScrReference[] {ScrReference.Empty, ScrReference.Empty}; ILocationTracker tracker = ((ITeView)Control).LocationTracker; // If there is a current book... BCVRef start = new BCVRef(); BCVRef end = new BCVRef(); int iBook = tracker.GetBookIndex(selection, selLimit); if (iBook >= 0 && BookFilter.BookCount > 0) { try { ScrBook book = BookFilter.GetBook(iBook); // if there is not a current section, then use the book and chapter/verse of 0. int hvoSection = tracker.GetSectionHvo(CurrentSelection, selLimit); if (hvoSection >= 0) { // If there is a section... ScrSection section = new ScrSection(m_cache, hvoSection); int paraHvo = selection.GetLevelInfoForTag( (int)StText.StTextTags.kflidParagraphs, selLimit).hvo; ScrTxtPara scrPara = new ScrTxtPara(m_cache, paraHvo); // Get the ich at either the beginning or the end of the selection, // as specified with limit. (NB that this is relative to the property, not the whole paragraph.) int ich; // Get the TsString, whether in vern or BT ITsString tss; SelLevInfo segInfo; int refWs; if (selection.GetLevelInfoForTag(StTxtPara.SegmentsFlid(Cache), selLimit, out segInfo)) { // selection is in a segmented BT segment. Figure the reference based on where the segment is // in the underlying paragraph. tss = scrPara.Contents.UnderlyingTsString; // for check below on range of ich. CmBaseAnnotation seg = new CmBaseAnnotation(Cache, segInfo.hvo); ich = seg.BeginOffset; Debug.Assert(seg.BeginObjectRAHvo == scrPara.Hvo); refWs = -1; // ich is in the paragraph itself, not some CmTranslation } else { ich = selection.GetIch(selLimit); // Get the TsString, whether in vern or BT tss = selection.GetTss(selLimit); refWs = GetCurrentBtWs(selLimit); // figures out whether it's in a CmTranslation or the para itself. } Debug.Assert(tss == null || ich <= tss.Length); if (tss != null && ich <= tss.Length) { scrPara.GetBCVRefAtPosition(refWs, ich, true, out start, out end); // If the chapter number is 0, then use the chapter from the section reference if (end.Chapter == 0) end.Chapter = BCVRef.GetChapterFromBcv(section.VerseRefMin); if (start.Chapter == 0) start.Chapter = BCVRef.GetChapterFromBcv(section.VerseRefMin); } } else { // either it didn't find a level or it didn't find an index. Either way, // it couldn't find a section. start.Book = end.Book = book.CanonicalNum; } } catch { // Bummer man, something went wrong... don't sweat it though, it happens... // This can occur if you are in the introduction or other location that lacks // relevant information or other necessary stuff. } } return new ScrReference[] {new ScrReference(start, m_scr.Versification), new ScrReference(end, m_scr.Versification)}; ; }
private void ValidateFocusBoxState(int indexWordExpected, InterlinDocChild idc, StTxtPara.TwficInfo twficBeforeEdit1_0, IStText stTextBeforeEdit) { IStText stTextAfterEdit = idc.RawStText; Assert.AreEqual(stTextBeforeEdit, stTextAfterEdit, "We expect to be in the same text."); int hvoAnnAfterEdit = idc.HvoAnnotation; ICmBaseAnnotation cbaAfterEdit = new CmBaseAnnotation(Cache, hvoAnnAfterEdit); Assert.IsFalse(twficBeforeEdit1_0.IsCapturedObjectInfoValid()); Assert.AreEqual(twficBeforeEdit1_0.BeginOffset, cbaAfterEdit.BeginOffset, "FocusBox should be at the same location."); Assert.AreNotEqual(twficBeforeEdit1_0.EndOffset, cbaAfterEdit.EndOffset, "FocusBox should now be on phrase annotation."); // FocusBox should be on phrase, not somewhere else. Assert.IsNotNull(idc.IsFocusBoxInstalled, "Focus Box should still be installed."); Assert.AreEqual(idc.ExistingFocusBox.InterlinWordControl.HvoAnnotation, hvoAnnAfterEdit, "FocusBox should be on current annotation."); // Make sure we haven't changed word in the wordform record list. int indexWordAfterEdit = m_wordList.CurrentIndex; int hvoWordAfterEdit = m_wordList.CurrentObject.Hvo; Assert.AreEqual(indexWordExpected, indexWordAfterEdit, "Word index mismatch"); }