int m_wsUr; // Urdu writing system (used for Foreign style) #endregion #region Test setup /// ------------------------------------------------------------------------------------ /// <summary> /// /// </summary> /// ------------------------------------------------------------------------------------ protected override void CreateTestData() { m_inMemoryCache.InitializeWritingSystemEncodings(); // create footnote m_footnote = new StFootnote(); m_book = (ScrBook)m_scrInMemoryCache.AddBookToMockedScripture(1, "Genesis"); m_book.FootnotesOS.Append(m_footnote); m_footnote.FootnoteMarker.Text = "o"; m_footnote.DisplayFootnoteMarker = true; m_footnote.DisplayFootnoteReference = false; // create one empty footnote para StTxtPara para = new StTxtPara(); m_footnote.ParagraphsOS.Append(para); para.StyleRules = StyleUtils.ParaStyleTextProps(ScrStyleNames.NormalFootnoteParagraph); m_strFact = TsStrFactoryClass.Create(); m_vernWs = Cache.LangProject.DefaultVernacularWritingSystem; para.Contents.UnderlyingTsString = m_strFact.MakeString(string.Empty, m_vernWs); m_footnotePara = (StTxtPara)m_footnote.ParagraphsOS[0]; m_wsUr = InMemoryFdoCache.s_wsHvos.Ur; // used with 'foreign' character style m_wsDe = InMemoryFdoCache.s_wsHvos.De; // used for back translations m_wsEs = InMemoryFdoCache.s_wsHvos.Es; }
public void TitleSecondary() { CheckDisposed(); m_importer.Settings.ImportBackTranslation = true; // initialize - process a \id segment to establish a book m_importer.TextSegment.FirstReference = new BCVRef(2, 0, 0); m_importer.TextSegment.LastReference = new BCVRef(2, 0, 0); m_importer.ProcessSegment("", @"\id"); // ************** process the title secondary style ********************* m_importer.ProcessSegment("Title secondary", @"\st"); m_importer.ProcessSegment("main title", @"\mt"); // ************** process a chapter ********************* m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 1); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 1); m_importer.ProcessSegment("", @"\c"); Assert.AreEqual(1, m_importer.Chapter); // ************** process v1 verse 1 ********************* m_importer.ProcessSegment("verse text", @"\v"); // verify state of NormalParaStrBldr Assert.AreEqual(3, m_importer.NormalParaStrBldr.RunCount); VerifyBldrRun(0, "1", ScrStyleNames.ChapterNumber); VerifyBldrRun(1, "1", ScrStyleNames.VerseNumber); VerifyBldrRun(2, "verse text", null); // ************** End of Scripture file ********************* // ******* Back translation in default Analysis WS ********** m_importer.CurrentImportDomain = ImportDomain.BackTrans; m_importer.DummySoWrapper.m_CurrentWs = m_wsAnal; // process an \id segment to establish a book m_importer.TextSegment.FirstReference = new BCVRef(2, 0, 0); m_importer.TextSegment.LastReference = new BCVRef(2, 0, 0); m_importer.ProcessSegment("", @"\id"); // ************** process the title secondary style ********************* m_importer.ProcessSegment("Title secondary BT", @"\st"); m_importer.ProcessSegment("main title BT", @"\mt"); // ************** process a chapter ********************* m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 1); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 1); m_importer.ProcessSegment("", @"\c"); Assert.AreEqual(1, m_importer.Chapter); // ************** process v1 verse 1 ********************* m_importer.ProcessSegment("back trans", @"\v"); // ******* Back translation in Spanish WS ********** int wsSpanish = Cache.LanguageWritingSystemFactoryAccessor.GetWsFromStr("es"); m_importer.DummySoWrapper.m_CurrentWs = wsSpanish; // process an \id segment to establish a book m_importer.TextSegment.FirstReference = new BCVRef(2, 0, 0); m_importer.TextSegment.LastReference = new BCVRef(2, 0, 0); m_importer.ProcessSegment("", @"\id"); // ************** process a chapter ********************* m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 1); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 1); m_importer.ProcessSegment("", @"\c"); Assert.AreEqual(1, m_importer.Chapter); // ************** process v1 verse 1 ********************* m_importer.ProcessSegment("retrotraduccion", @"\v"); // ************** finalize ************** m_importer.FinalizeImport(); IScrBook book = new ScrBook(Cache, m_importer.ScrBook.Hvo); StTxtPara para = (StTxtPara)book.TitleOA.ParagraphsOS[0]; Assert.AreEqual("Title secondary\u2028main title", para.Contents.Text); Assert.AreEqual(1, para.TranslationsOC.Count); ICmTranslation trans = para.GetBT(); // Check default analysis BT TsStringAccessor bt = trans.Translation.AnalysisDefaultWritingSystem; Assert.AreEqual("Title secondary BT\u2028main title BT", bt.Text); Assert.AreEqual(2, bt.UnderlyingTsString.RunCount); AssertEx.RunIsCorrect(bt.UnderlyingTsString, 0, "Title secondary BT", "Title Secondary", m_scr.Cache.DefaultAnalWs); AssertEx.RunIsCorrect(bt.UnderlyingTsString, 1, "\u2028main title BT", null, m_scr.Cache.DefaultAnalWs); }
/// <summary> /// Executes in two distinct scenarios. /// /// 1. If disposing is true, the method has been called directly /// or indirectly by a user's code via the Dispose method. /// Both managed and unmanaged resources can be disposed. /// /// 2. If disposing is false, the method has been called by the /// runtime from inside the finalizer and you should not reference (access) /// other managed objects, as they already have been garbage collected. /// Only unmanaged resources can be disposed. /// </summary> /// <param name="disposing"></param> /// <remarks> /// If any exceptions are thrown, that is fine. /// If the method is being done in a finalizer, it will be ignored. /// If it is thrown by client code calling Dispose, /// it needs to be handled by fixing the bug. /// /// If subclasses override this method, they should call the base implementation. /// </remarks> 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) { // Dispose managed resources here. } // Dispose unmanaged resources here, whether disposing is true or false. m_footnote = null;; m_book = null; if (m_strFact != null) Marshal.ReleaseComObject(m_strFact); m_strFact = null;; base.Dispose(disposing); }
public void MergeBTsWhenParasMerge_FromMiddleOfPara1ToMiddleOfPara2_aKey() { CheckDisposed(); ShowForm(Lng.English, DummyBasicViewVc.DisplayType.kNormal); IVwRootBox rootBox = m_basicView.RootBox; // Add a second paragraph to the first text and create some Back Translations on // both paragraphs ScrBook book = new ScrBook(Cache, m_hvoRoot); StText text1 = (StText)book.FootnotesOS[0]; StTxtPara para1 = (StTxtPara)text1.ParagraphsOS[0]; StTxtPara para2 = m_scrInMemoryCache.AddParaToMockedText(text1.Hvo, string.Empty); m_scrInMemoryCache.AddRunToMockedPara(para2, DummyBasicView.kSecondParaEng, m_wsEng); // We'll just re-use our "vernacular" WS for the back translation, for testing purposes. ICmTranslation trans1 = m_inMemoryCache.AddBtToMockedParagraph(para1, m_wsEng); m_inMemoryCache.AddRunToMockedTrans(trans1, m_wsEng, "BT1", null); ICmTranslation trans2 = m_inMemoryCache.AddBtToMockedParagraph(para2, m_wsEng); m_inMemoryCache.AddRunToMockedTrans(trans2, m_wsEng, "BT2", null); Cache.PropChanged(null, PropChangeType.kpctNotifyAll, text1.Hvo, (int)StText.StTextTags.kflidParagraphs, 1, 1, 0); // Make a selection from the end of first paragraph to the beginning of the second. SelLevInfo[] levelInfo = new SelLevInfo[2]; levelInfo[1].tag = m_flidContainingTexts; levelInfo[1].cpropPrevious = 0; levelInfo[1].ihvo = 0; levelInfo[0].tag = (int)StText.StTextTags.kflidParagraphs; levelInfo[0].cpropPrevious = 0; levelInfo[0].ihvo = 0; int ichAnchor = DummyBasicView.kFirstParaEng.Length - 2; int ichEnd = 2; rootBox.MakeTextSelection(0, 2, levelInfo, (int)StTxtPara.StTxtParaTags.kflidContents, 0, ichAnchor, ichEnd, 0, true, 1, null, true); TypeChar('a'); Assert.AreEqual(DummyBasicView.kFirstParaEng.Substring(0, ichAnchor) + "a" + DummyBasicView.kSecondParaEng.Substring(ichEnd), para1.Contents.Text); Assert.AreEqual("BT1 BT2", trans1.Translation.GetAlternative(m_wsEng).Text); }
public void MergeTranslationsWhenParasMerge_FirstParaHasNoTranslations() { CheckDisposed(); ShowForm(Lng.English, DummyBasicViewVc.DisplayType.kNormal); IVwRootBox rootBox = m_basicView.RootBox; // Add a second paragraph to the first text and create some translations on // both paragraphs ScrBook book = new ScrBook(Cache, m_hvoRoot); StText text1 = (StText)book.FootnotesOS[0]; StTxtPara para1 = (StTxtPara)text1.ParagraphsOS[0]; StTxtPara para2 = m_inMemoryCache.AddParaToMockedText(text1.Hvo, string.Empty); m_inMemoryCache.AddRunToMockedPara(para2, DummyBasicView.kSecondParaEng, m_wsEng); // We'll just re-use our "vernacular" WS for the translations, for testing purposes. ICmTranslation bt2 = m_inMemoryCache.AddBtToMockedParagraph(para2, m_wsEng); m_inMemoryCache.AddRunToMockedTrans(bt2, m_wsEng, "BT2", null); ICmTranslation free2 = m_inMemoryCache.AddTransToMockedParagraph(para2, LangProject.kguidTranFreeTranslation, m_wsEng); m_inMemoryCache.AddRunToMockedTrans(free2, m_wsEng, "Free2", null); ICmTranslation lit2 = m_inMemoryCache.AddTransToMockedParagraph(para2, LangProject.kguidTranLiteralTranslation, m_wsEng); m_inMemoryCache.AddRunToMockedTrans(lit2, m_wsEng, "Lit2", null); Cache.PropChanged(null, PropChangeType.kpctNotifyAll, text1.Hvo, (int)StText.StTextTags.kflidParagraphs, 1, 1, 0); // Make a selection from the end of first paragraph to the beginning of the second. SelLevInfo[] levelInfo = new SelLevInfo[2]; levelInfo[1].tag = m_flidContainingTexts; levelInfo[1].cpropPrevious = 0; levelInfo[1].ihvo = 0; levelInfo[0].tag = (int)StText.StTextTags.kflidParagraphs; levelInfo[0].cpropPrevious = 0; levelInfo[0].ihvo = 0; int ich = DummyBasicView.kFirstParaEng.Length; rootBox.MakeTextSelection(0, 2, levelInfo, (int)StTxtPara.StTxtParaTags.kflidContents, 0, ich, 0, 0, true, 1, null, true); TypeBackspace(); Assert.AreEqual(DummyBasicView.kFirstParaEng + DummyBasicView.kSecondParaEng, para1.Contents.Text); ICmTranslation bt1 = para1.GetBT(); Assert.AreEqual("BT2", bt1.Translation.GetAlternative(m_wsEng).Text); ICmTranslation free1 = para1.GetTrans(LangProject.kguidTranFreeTranslation); Assert.AreEqual("Free2", free1.Translation.GetAlternative(m_wsEng).Text); ICmTranslation lit1 = para1.GetTrans(LangProject.kguidTranLiteralTranslation); Assert.AreEqual("Lit2", lit1.Translation.GetAlternative(m_wsEng).Text); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Merges content of given section into the content of the previous section and then /// deletes the given section. /// </summary> /// <param name="helper"> </param> /// <param name="book"></param> /// <param name="section"></param> /// <param name="ihvoSection"></param> /// <param name="fPositionAtEnd">If true position of Selection is placed at end of /// paragraph, else at the beginning.</param> /// ------------------------------------------------------------------------------------ private void MergeContentWithPreviousSection(SelectionHelper helper, ScrBook book, IScrSection section, int ihvoSection, bool fPositionAtEnd) { //REVIEW: Can the methods that call this be refactored //to use (a refactored?) ScrSection.MergeWithPreviousSection? // // Get the previous section and move the paragraphs. IScrSection sectionPrev = book.SectionsOS[ihvoSection - 1]; IStText textPrev = sectionPrev.ContentOA; ILocationTracker tracker = ((ITeView)Control).LocationTracker; int iBook = tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Top); int cparaPrev = 0; if (textPrev == null) { // Prevent crash when dealing with corrupt database (TE-4869) // Since the previous section doesn't have a text, we simply move the entire text // object from the current section to the previous section. m_cache.ChangeOwner(section.ContentOAHvo, sectionPrev.Hvo, (int)ScrSection.ScrSectionTags.kflidContent); } else { cparaPrev = textPrev.ParagraphsOS.Count; IStText textOldContents = section.ContentOA; m_cache.MoveOwningSequence(textOldContents.Hvo, (int)StText.StTextTags.kflidParagraphs, 0, textOldContents.ParagraphsOS.Count - 1, textPrev.Hvo, (int)StText.StTextTags.kflidParagraphs, cparaPrev); } // protected for some reason...textPrev.ParagraphsOS.Append(text.ParagraphsOS.HvoArray); book.SectionsOS.RemoveAt(ihvoSection); // Now we have to re-establish a selection. Whatever happens, it will be in the // same book as before, and the previous section, and in the body. if (InSectionHead || !fPositionAtEnd) { tracker.SetBookAndSection(helper, SelectionHelper.SelLimitType.Top, iBook, ihvoSection - 1); helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[1].tag = (int)ScrSection.ScrSectionTags.kflidContent; } Debug.Assert(helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[1].tag == (int)ScrSection.ScrSectionTags.kflidContent); if (fPositionAtEnd) { // we want selection at end of last paragraph of old previous section. // (That is, at the end of paragraph cparaPrev - 1.) Debug.Assert(cparaPrev > 0); helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[0].ihvo = cparaPrev - 1; StTxtPara paraPrev = (StTxtPara)(textPrev.ParagraphsOS[cparaPrev - 1]); int cchParaPrev = paraPrev.Contents.Length; helper.IchAnchor = cchParaPrev; helper.IchEnd = cchParaPrev; helper.AssocPrev = true; } else { // want selection at start of old first paragraph of deleted section. // (That is, at the start of paragraph cparaPrev.) helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[0].ihvo = cparaPrev; helper.IchAnchor = 0; helper.IchEnd = 0; helper.AssocPrev = false; } helper.SetLevelInfo(SelectionHelper.SelLimitType.Bottom, helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)); helper.SetSelection(true); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Handles deletion of empty section content paragraph on backspace key being pressed /// at text boundary. /// </summary> /// <param name="helper">The selection helper.</param> /// <returns><c>true</c> if we merged the sections, otherwise <c>false</c>.</returns> /// ------------------------------------------------------------------------------------ private bool HandleBackspaceAfterEmptyContentParagraph(SelectionHelper helper) { SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top); ILocationTracker tracker = ((ITeView)Control).LocationTracker; ScrBook book = new ScrBook(m_cache, tracker.GetBookHvo(helper, SelectionHelper.SelLimitType.Top)); int iSection = tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top); if (iSection == 0) return false; IScrSection prevSection = book.SectionsOS[iSection - 1]; int cParas = prevSection.ContentOA != null ? prevSection.ContentOA.ParagraphsOS.Count : 0; if (cParas > 0) { // If we are the beginning of heading before a multi-paragraph content // and the last paragraph is empty, we delete the last paragraph of // the content. if (cParas > 1) { StTxtPara para = (StTxtPara)prevSection.ContentOA.ParagraphsOS[cParas - 1]; if (para.Contents.Length == 0) { prevSection.ContentOA.ParagraphsOS.RemoveAt(cParas - 1); return true; } } // If we are at beginning of heading before an empty section content and // not in the first section, we should merge sections. else { StTxtPara para = (StTxtPara)prevSection.ContentOA.ParagraphsOS[cParas - 1]; if (para.Contents.Length == 0) { return MergeWithFollowingSectionIfInSameContext(helper, book, iSection - 1, prevSection, false); } } } else { return MergeWithFollowingSectionIfInSameContext(helper, book, iSection - 1, prevSection, false); } return false; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Handles deletion of empty section content paragraph on delete key being pressed at /// text boundary. /// </summary> /// <param name="helper">The selection helper.</param> /// <returns><c>true</c> if we merged the sections, otherwise <c>false</c>.</returns> /// ------------------------------------------------------------------------------------ private bool HandleDeleteBeforeEmptySectionContentParagraph(SelectionHelper helper) { // delete problem deletion will occur at end of section heading SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top); ILocationTracker tracker = ((ITeView)Control).LocationTracker; ScrBook book = new ScrBook(m_cache, tracker.GetBookHvo(helper, SelectionHelper.SelLimitType.Top)); int iSection = tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top); IScrSection section = book.SectionsOS[iSection]; int cParas = section.ContentOA != null ? section.ContentOA.ParagraphsOS.Count : 0; if (cParas > 0) { // If we are the end of heading before a multi-paragraph content // and the first paragraph is empty, we delete the first paragraph of // the content. if (cParas > 1) { StTxtPara para = (StTxtPara)section.ContentOA.ParagraphsOS[0]; if (para.Contents.Length == 0) { section.ContentOA.ParagraphsOS.RemoveAt(0); return true; } } // If we are at end of section heading or beginning of section content // and not in the last section, we should merge sections. else { if (iSection == book.SectionsOS.Count - 1) return false; StTxtPara para = (StTxtPara)section.ContentOA.ParagraphsOS[0]; if (para.Contents.Length == 0) { return MergeWithFollowingSectionIfInSameContext(helper, book, iSection, section, true); } } } else { return MergeWithFollowingSectionIfInSameContext(helper, book, iSection, section, true); } return false; }
/// ----------------------------------------------------------------------------------- /// <summary> /// Get a string that describes the Scripture passage based on the selection. /// </summary> /// <param name="tag">The flid of the selected element</param> /// <param name="hvoSel">The hvo of the selected element, either a ScrSection (usually) /// or ScrBook (if in a title)</param> /// <param name="fSimpleFormat">Gets a simple, standardized reference (uses SIL 3-letter /// codes and no verse bridges)</param> /// <returns>String that describes the Scripture passage or null if the selection /// can't be interpreted as a book and/or section reference.</returns> /// ----------------------------------------------------------------------------------- public virtual string GetPassageAsString(int tag, int hvoSel, bool fSimpleFormat) { CheckDisposed(); if (m_cache == null) return null; string sEditRef = null; // Title/reference/etc of text being edited in the draft pane switch (tag) { case (int)ScrSection.ScrSectionTags.kflidHeading: case (int)ScrSection.ScrSectionTags.kflidContent: { // ENHANCE TomB: might want to use low-level methods to get // cached values directly instead of creating the FDO objects // and having them reread the info from the DB. Also, may want // to cache the hvoSel in a method static variable so that when // the selection hasn't really changed to a new section or book, // we stop here. ScrSection section = new ScrSection(m_cache, hvoSel, false, false); BCVRef startRef; BCVRef endRef; section.GetDisplayRefs(out startRef, out endRef); if (fSimpleFormat) sEditRef = startRef.AsString; else { sEditRef = ScrReference.MakeReferenceString(section.OwningBook.BestUIName, startRef, endRef, m_scr.ChapterVerseSepr, m_scr.Bridge); } break; } case (int)ScrBook.ScrBookTags.kflidTitle: { ScrBook book = new ScrBook(m_cache, hvoSel, false, false); sEditRef = (fSimpleFormat ? (book.BookId + " 0:0") : book.BestUIName); break; } default: return null; } // Add the back translation writing system info to the output string, if needed if (IsBackTranslation) { LgWritingSystem ws = new LgWritingSystem(m_cache, ViewConstructorWS); sEditRef = string.Format( TeResourceHelper.GetResourceString("kstidCaptionInBackTrans"), sEditRef, ws.Name.UserDefaultWritingSystem); } return (sEditRef != null && sEditRef.Length != 0) ? sEditRef : null; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Scrolls the requested footnote to the top of the view /// </summary> /// <param name="footnote">The target footnote</param> /// <param name="fPutInsertionPtAtEnd">if set to <c>true</c> and showing the view, /// the insertion point will be put at the end of the footnote text instead of at the /// beginning, as would be appropriate in the case of a newly inserted footnote that has /// Reference Text. This parameter is ignored if footnote is null.</param> /// ------------------------------------------------------------------------------------ public void ScrollToFootnote(StFootnote footnote, bool fPutInsertionPtAtEnd) { CheckDisposed(); // find book owning this footnote int iBook = m_bookFilter.GetBookIndex(footnote.OwnerHVO); ScrBook book = new ScrBook(Cache, footnote.OwnerHVO); // find index of this footnote int iFootnote = footnote.IndexInOwner; // create selection pointing to this footnote FootnoteEditingHelper.ScrollToFootnote(iBook, iFootnote, (fPutInsertionPtAtEnd ? ((StTxtPara)footnote.ParagraphsOS[0]).Contents.Length: 0)); }
public void BtOnlyFootnotes() { m_scrInMemoryCache.InitializeScrPublications(); // Set up Scripture to correspond with the back translation to be imported. IScrBook exodus = m_scrInMemoryCache.AddBookToMockedScripture(2, "Exodus"); IScrSection section = m_scrInMemoryCache.AddSectionToMockedBook(exodus.Hvo); StTxtPara para = m_scrInMemoryCache.AddParaToMockedSectionContent(section.Hvo, ScrStyleNames.NormalParagraph); m_scrInMemoryCache.AddRunToMockedPara(para, "1", ScrStyleNames.ChapterNumber); m_scrInMemoryCache.AddRunToMockedPara(para, "1", ScrStyleNames.VerseNumber); m_scrInMemoryCache.AddRunToMockedPara(para, "verse one text", null); m_scrInMemoryCache.AddRunToMockedPara(para, "2", ScrStyleNames.VerseNumber); m_scrInMemoryCache.AddRunToMockedPara(para, "verse two text", null); StFootnote noteOne = m_scrInMemoryCache.AddFootnote(exodus, para, 11, "vernacular text for footnote one"); // footnote after "one" in verse 1 StFootnote noteTwo = m_scrInMemoryCache.AddFootnote(exodus, para, 27, "vernacular text for footnote two"); // footnote after "two" in verse 2 ICmTranslation noteOneTrans = ((StTxtPara)noteOne.ParagraphsOS[0]).GetOrCreateBT(); ICmTranslation noteTwoTrans = ((StTxtPara)noteTwo.ParagraphsOS[0]).GetOrCreateBT(); section.AdjustReferences(); m_importer.Settings.ImportTranslation = false; m_importer.Settings.ImportBackTranslation = true; m_importer.CurrentImportDomain = ImportDomain.BackTrans; // ************** process a \id segment, test MakeBook() method ********************* m_importer.TextSegment.FirstReference = new BCVRef(2, 0, 0); m_importer.TextSegment.LastReference = new BCVRef(2, 0, 0); m_importer.ProcessSegment("", @"\id"); // no text provided in segment, just the refs Assert.AreEqual(2, m_importer.BookNumber); // verify that a new book was added to the DB IScrBook book = new ScrBook(Cache, m_importer.ScrBook.Hvo); Assert.AreEqual("EXO", book.BookId); // ************** process a main title ********************* m_importer.ProcessSegment(string.Empty, @"\mt"); // ************** process a chapter ********************* m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 0); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 0); m_importer.ProcessSegment("", @"\c"); // ****** process a new BT paragraph with footnotes ********** m_importer.ProcessSegment("", @"\p"); m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 1); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 1); m_importer.ProcessSegment("", @"\v"); m_importer.ProcessSegment("verse one BT text", @"\vt"); m_importer.ProcessSegment("+", @"\f"); m_importer.ProcessSegment("BT text for footnote one.", @"\ft"); m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 2); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 2); m_importer.ProcessSegment("", @"\v"); m_importer.ProcessSegment("verse two BT text", @"\vt"); m_importer.ProcessSegment("+", @"\f"); m_importer.ProcessSegment("BT text for footnote two.", @"\ft"); // ************** finalize ************** m_importer.FinalizeImport(); // Check the BT of these two paragraphs Assert.AreEqual(1, para.TranslationsOC.Count); ICmTranslation trans1 = para.GetBT(); Assert.IsNotNull(trans1); ITsString tss1 = trans1.Translation.AnalysisDefaultWritingSystem.UnderlyingTsString; //Assert.AreEqual(7, tss1.RunCount); AssertEx.RunIsCorrect(tss1, 0, "1", ScrStyleNames.ChapterNumber, m_wsAnal); AssertEx.RunIsCorrect(tss1, 1, "1", ScrStyleNames.VerseNumber, m_wsAnal); AssertEx.RunIsCorrect(tss1, 2, "verse one BT text", null, m_wsAnal); Guid guid1 = StringUtils.GetGuidFromRun(tss1, 3); int hvoFootnote = Cache.GetIdFromGuid(guid1); Assert.AreEqual(noteOneTrans.OwnerHVO, new StFootnote(Cache, hvoFootnote).ParagraphsOS[0].Hvo, "The first imported BT footnote should be owned by paragraph in the first footnote but isn't"); VerifyFootnoteWithTranslation(0, "vernacular text for footnote one", "BT text for footnote one.", null, ScrStyleNames.NormalFootnoteParagraph); AssertEx.RunIsCorrect(tss1, 4, "2", ScrStyleNames.VerseNumber, m_wsAnal); AssertEx.RunIsCorrect(tss1, 5, "verse two BT text", null, m_wsAnal); VerifyFootnoteWithTranslation(1, "vernacular text for footnote two", "BT text for footnote two.", null, ScrStyleNames.NormalFootnoteParagraph); }
public void TwoBts() { CheckDisposed(); m_importer.Settings.ImportBackTranslation = true; // initialize - process a \id segment to establish a book m_importer.TextSegment.FirstReference = new BCVRef(2, 0, 0); m_importer.TextSegment.LastReference = new BCVRef(2, 0, 0); m_importer.ProcessSegment("EXO Vernacular ID Text", @"\id"); // ************** process a chapter ********************* m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 1); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 1); m_importer.ProcessSegment("", @"\c"); Assert.AreEqual(1, m_importer.Chapter); // ************** process v1 verse 1 ********************* m_importer.ProcessSegment("verse text", @"\v"); // verify state of NormalParaStrBldr Assert.AreEqual(3, m_importer.NormalParaStrBldr.RunCount); VerifyBldrRun(0, "1", ScrStyleNames.ChapterNumber); VerifyBldrRun(1, "1", ScrStyleNames.VerseNumber); VerifyBldrRun(2, "verse text", null); // ************** End of Scripture file ********************* // ******* Back translation in default Analysis WS ********** m_importer.CurrentImportDomain = ImportDomain.BackTrans; m_importer.DummySoWrapper.m_CurrentWs = m_wsAnal; // process an \id segment to establish a book m_importer.TextSegment.FirstReference = new BCVRef(2, 0, 0); m_importer.TextSegment.LastReference = new BCVRef(2, 0, 0); m_importer.ProcessSegment("EXO Ignore this", @"\id"); // ************** process a chapter ********************* m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 1); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 1); m_importer.ProcessSegment("", @"\c"); Assert.AreEqual(1, m_importer.Chapter); // ************** process v1 verse 1 ********************* m_importer.ProcessSegment("back trans", @"\v"); // ******* Back translation in Spanish WS ********** int wsSpanish = Cache.LanguageWritingSystemFactoryAccessor.GetWsFromStr("es"); m_importer.DummySoWrapper.m_CurrentWs = wsSpanish; // process an \id segment to establish a book m_importer.TextSegment.FirstReference = new BCVRef(2, 0, 0); m_importer.TextSegment.LastReference = new BCVRef(2, 0, 0); m_importer.ProcessSegment("EXO Ignora esto tambien", @"\id"); // ************** process a chapter ********************* m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 1); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 1); m_importer.ProcessSegment("", @"\c"); Assert.AreEqual(1, m_importer.Chapter); // ************** process v1 verse 1 ********************* m_importer.ProcessSegment("retrotraduccion", @"\v"); // ************** finalize ************** m_importer.FinalizeImport(); IScrBook book = new ScrBook(Cache, m_importer.ScrBook.Hvo); Assert.AreEqual("Vernacular ID Text", book.IdText); Assert.AreEqual(1, book.SectionsOS.Count); IScrSection section = book.SectionsOS[0]; Assert.AreEqual(1, section.ContentOA.ParagraphsOS.Count); Assert.AreEqual(02001001, section.VerseRefMin); Assert.AreEqual(02001001, section.VerseRefMax); StTxtPara para = (StTxtPara)section.ContentOA.ParagraphsOS[0]; Assert.AreEqual("11verse text", para.Contents.Text); Assert.AreEqual(1, para.TranslationsOC.Count); ICmTranslation trans = para.GetBT(); // Check default analysis BT TsStringAccessor bt = trans.Translation.AnalysisDefaultWritingSystem; Assert.AreEqual("11back trans", bt.Text); Assert.AreEqual(3, bt.UnderlyingTsString.RunCount); Assert.AreEqual("back trans", bt.UnderlyingTsString.get_RunText(2)); ITsTextProps ttpRun3 = bt.UnderlyingTsString.get_Properties(2); Assert.AreEqual(null, ttpRun3.GetStrPropValue((int)FwTextPropType.ktptNamedStyle)); int nVar; Assert.AreEqual(m_wsAnal, ttpRun3.GetIntPropValues((int)FwTextPropType.ktptWs, out nVar)); // Check Spanish BT bt = trans.Translation.GetAlternative(wsSpanish); Assert.AreEqual("11retrotraduccion", bt.Text); Assert.AreEqual(3, bt.UnderlyingTsString.RunCount); Assert.AreEqual("retrotraduccion", bt.UnderlyingTsString.get_RunText(2)); ttpRun3 = bt.UnderlyingTsString.get_Properties(2); Assert.AreEqual(null, ttpRun3.GetStrPropValue((int)FwTextPropType.ktptNamedStyle)); Assert.AreEqual(wsSpanish, ttpRun3.GetIntPropValues((int)FwTextPropType.ktptWs, out nVar)); }
public void ImplicitParaStart() { CheckDisposed(); m_scrInMemoryCache.InitializeScrPublications(); // Set up Scripture to correspond with the back translation to be imported. IScrBook exodus = m_scrInMemoryCache.AddBookToMockedScripture(2, "Exodus"); IScrSection section1 = m_scrInMemoryCache.AddSectionToMockedBook(exodus.Hvo); StTxtPara para1 = m_scrInMemoryCache.AddParaToMockedSectionContent(section1.Hvo, ScrStyleNames.NormalParagraph); m_scrInMemoryCache.AddRunToMockedPara(para1, "1", ScrStyleNames.ChapterNumber); m_scrInMemoryCache.AddRunToMockedPara(para1, "1", ScrStyleNames.VerseNumber); m_scrInMemoryCache.AddRunToMockedPara(para1, "verse one text", null); m_scrInMemoryCache.AddRunToMockedPara(para1, "2", ScrStyleNames.VerseNumber); m_scrInMemoryCache.AddRunToMockedPara(para1, "verse two text", null); StTxtPara para2 = m_scrInMemoryCache.AddParaToMockedSectionContent(section1.Hvo, "List Item1"); m_scrInMemoryCache.AddRunToMockedPara(para2, "more verse two text", null); section1.AdjustReferences(); m_importer.Settings.ImportBackTranslation = true; m_importer.CurrentImportDomain = ImportDomain.BackTrans; // ************** process a \id segment, test MakeBook() method ********************* m_importer.TextSegment.FirstReference = new BCVRef(2, 0, 0); m_importer.TextSegment.LastReference = new BCVRef(2, 0, 0); m_importer.ProcessSegment("", @"\id"); // no text provided in segment, just the refs Assert.AreEqual(2, m_importer.BookNumber); IScrBook book = new ScrBook(Cache, m_importer.ScrBook.Hvo); Assert.AreEqual("EXO", book.BookId); // ************** process a main title ********************* m_importer.ProcessSegment(string.Empty, @"\mt"); //Assert.AreEqual(string.Empty, m_importer.ScrBook.Name.GetAlternative( // m_wsAnal)); // ************** process a chapter ********************* m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 0); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 0); m_importer.ProcessSegment("", @"\c"); // ************** process two new paragraphs ********************* m_importer.ProcessSegment("", @"\p"); m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 1); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 1); m_importer.ProcessSegment("", @"\v"); m_importer.ProcessSegment("BT text for verse one", @"\vt"); m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 2); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 2); m_importer.ProcessSegment("", @"\v"); m_importer.ProcessSegment("BT for text at start of verse 2", @"\vt"); m_importer.ProcessSegment("", @"\li1"); m_importer.ProcessSegment("BT of continued text", @"\vt"); // ************** finalize ************** m_importer.FinalizeImport(); // Check the BT of these two paragraphs Assert.AreEqual(1, para1.TranslationsOC.Count); ICmTranslation trans1 = para1.GetBT(); ITsString tss1 = trans1.Translation.AnalysisDefaultWritingSystem.UnderlyingTsString; Assert.AreEqual(5, tss1.RunCount); AssertEx.RunIsCorrect(tss1, 0, "1", ScrStyleNames.ChapterNumber, m_wsAnal); AssertEx.RunIsCorrect(tss1, 1, "1", ScrStyleNames.VerseNumber, m_wsAnal); AssertEx.RunIsCorrect(tss1, 2, "BT text for verse one", null, m_wsAnal); AssertEx.RunIsCorrect(tss1, 3, "2", ScrStyleNames.VerseNumber, m_wsAnal); AssertEx.RunIsCorrect(tss1, 4, "BT for text at start of verse 2", null, m_wsAnal); Assert.AreEqual(1, para2.TranslationsOC.Count); ICmTranslation trans2 = para2.GetBT(); ITsString tss2 = trans2.Translation.AnalysisDefaultWritingSystem.UnderlyingTsString; Assert.AreEqual(1, tss2.RunCount); }
public void VerseBeyondVersificationMax() { CheckDisposed(); m_importer.Settings.ImportBackTranslation = true; // initialize - process a \id segment to establish a book m_importer.TextSegment.FirstReference = new BCVRef(45, 7, 25); m_importer.TextSegment.LastReference = new BCVRef(45, 7, 25); m_importer.ProcessSegment("", @"\id"); m_importer.ProcessSegment("", @"\c"); // ************** process two new paragraphs ********************* m_importer.ProcessSegment("", @"\p"); m_importer.ProcessSegment("", @"\v"); m_importer.ProcessSegment("Front text for verse25", @"\vt"); m_importer.TextSegment.FirstReference = new BCVRef(45, 7, 26); m_importer.TextSegment.LastReference = new BCVRef(45, 7, 26); m_importer.ProcessSegment("", @"\v"); m_importer.ProcessSegment("Front text for verse26", @"\vt"); //// verify state of NormalParaStrBldr Assert.AreEqual(5, m_importer.NormalParaStrBldr.RunCount); VerifyBldrRun(0, "7", ScrStyleNames.ChapterNumber); VerifyBldrRun(1, "25", ScrStyleNames.VerseNumber); VerifyBldrRun(2, "Front text for verse25", null); VerifyBldrRun(3, "26", ScrStyleNames.VerseNumber); VerifyBldrRun(4, "Front text for verse26", null); // ************** End of Scripture file ********************* // ******* Back translation in default Analysis WS ********** m_importer.CurrentImportDomain = ImportDomain.BackTrans; m_importer.DummySoWrapper.m_CurrentWs = m_wsAnal; // process an \id segment to establish a book m_importer.TextSegment.FirstReference = new BCVRef(45, 7, 26); m_importer.TextSegment.LastReference = new BCVRef(45, 7, 26); m_importer.ProcessSegment("", @"\id"); m_importer.ProcessSegment("", @"\c"); // ************** process two new paragraphs ********************* m_importer.ProcessSegment("", @"\p"); m_importer.ProcessSegment("", @"\v"); m_importer.ProcessSegment("Back text for verse", @"\vt"); // ************** finalize ************** m_importer.FinalizeImport(); IScrBook book = new ScrBook(Cache, m_importer.ScrBook.Hvo); // Check section 1 StTxtPara para = (StTxtPara)book.SectionsOS[0].ContentOA.ParagraphsOS[0]; Assert.AreEqual("725Front text for verse2526Front text for verse26", para.Contents.Text); Assert.AreEqual(1, para.TranslationsOC.Count); ICmTranslation trans = para.GetBT(); // Check default analysis BT TsStringAccessor bt = trans.Translation.AnalysisDefaultWritingSystem; Assert.AreEqual("726Back text for verse", bt.Text); Assert.AreEqual(3, bt.UnderlyingTsString.RunCount); AssertEx.RunIsCorrect(bt.UnderlyingTsString, 0, "7", ScrStyleNames.ChapterNumber, m_scr.Cache.DefaultAnalWs); AssertEx.RunIsCorrect(bt.UnderlyingTsString, 1, "26", ScrStyleNames.VerseNumber, m_scr.Cache.DefaultAnalWs); AssertEx.RunIsCorrect(bt.UnderlyingTsString, 2, "Back text for verse", null, m_scr.Cache.DefaultAnalWs); }
public void DoubleSectionHeadMarker() { CheckDisposed(); m_importer.Settings.ImportBackTranslation = true; // initialize - process a \id segment to establish a book m_importer.TextSegment.FirstReference = new BCVRef(2, 0, 0); m_importer.TextSegment.LastReference = new BCVRef(2, 0, 0); m_importer.ProcessSegment("", @"\id"); // ************** process the two-line section head *************** m_importer.ProcessSegment("Front Section head 1.1", @"\s"); m_importer.ProcessSegment("Front Section head 1.2", @"\s"); //// verify state of NormalParaStrBldr Assert.AreEqual(1, m_importer.NormalParaStrBldr.RunCount); VerifyBldrRun(0, "Front Section head 1.1\u2028Front Section head 1.2", null); // ************** process a chapter ********************* m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 1); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 1); m_importer.ProcessSegment("", @"\c"); Assert.AreEqual(1, m_importer.Chapter); // ************** process v1 verse 1 ********************* m_importer.ProcessSegment("Some verse", @"\v"); // ************** process another two-line section head ************** m_importer.ProcessSegment("Front Section head 2.1", @"\s"); m_importer.ProcessSegment("Front Section head 2.2", @"\s"); //// verify state of NormalParaStrBldr Assert.AreEqual(1, m_importer.NormalParaStrBldr.RunCount); VerifyBldrRun(0, "Front Section head 2.1\u2028Front Section head 2.2", null); // ************** End of Scripture file ********************* // ******* Back translation in default Analysis WS ********** m_importer.CurrentImportDomain = ImportDomain.BackTrans; m_importer.DummySoWrapper.m_CurrentWs = m_wsAnal; // process an \id segment to establish a book m_importer.TextSegment.FirstReference = new BCVRef(2, 0, 0); m_importer.TextSegment.LastReference = new BCVRef(2, 0, 0); m_importer.ProcessSegment("", @"\id"); // ************** process the BT of section head 1 ************** m_importer.ProcessSegment("Back Section head 1.1", @"\s"); m_importer.ProcessSegment("Back Section head 1.2", @"\s"); // ************** process a chapter ********************* m_importer.TextSegment.FirstReference = new BCVRef(2, 1, 1); m_importer.TextSegment.LastReference = new BCVRef(2, 1, 1); m_importer.ProcessSegment("", @"\c"); Assert.AreEqual(1, m_importer.Chapter); // ************** process v1 verse 1 ********************* m_importer.ProcessSegment("Algun versiculo", @"\v"); // ************** process the BT of section head 2 ************** m_importer.ProcessSegment("Back Section head 2.1", @"\s"); m_importer.ProcessSegment("Back Section head 2.2", @"\s"); // ************** finalize ************** m_importer.FinalizeImport(); IScrBook book = new ScrBook(Cache, m_importer.ScrBook.Hvo); // Check section 1 StTxtPara para = (StTxtPara)book.SectionsOS[0].HeadingOA.ParagraphsOS[0]; Assert.AreEqual("Front Section head 1.1\u2028Front Section head 1.2", para.Contents.Text); Assert.AreEqual(1, para.TranslationsOC.Count); ICmTranslation trans = para.GetBT(); // Check default analysis BT TsStringAccessor bt = trans.Translation.AnalysisDefaultWritingSystem; Assert.AreEqual("Back Section head 1.1\u2028Back Section head 1.2", bt.Text); Assert.AreEqual(1, bt.UnderlyingTsString.RunCount); AssertEx.RunIsCorrect(bt.UnderlyingTsString, 0, "Back Section head 1.1\u2028Back Section head 1.2", null, m_scr.Cache.DefaultAnalWs); // Check section 2 para = (StTxtPara)book.SectionsOS[1].HeadingOA.ParagraphsOS[0]; Assert.AreEqual("Front Section head 2.1\u2028Front Section head 2.2", para.Contents.Text); Assert.AreEqual(1, para.TranslationsOC.Count); trans = para.GetBT(); // Check default analysis BT bt = trans.Translation.AnalysisDefaultWritingSystem; Assert.AreEqual("Back Section head 2.1\u2028Back Section head 2.2", bt.Text); Assert.AreEqual(1, bt.UnderlyingTsString.RunCount); AssertEx.RunIsCorrect(bt.UnderlyingTsString, 0, "Back Section head 2.1\u2028Back Section head 2.2", null, m_scr.Cache.DefaultAnalWs); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Handles deletion of empty section heading paragraph on backspace key being pressed /// at text boundary. /// </summary> /// <param name="helper">The selection helper.</param> /// <returns><c>true</c> if we handled the deletion, otherwise <c>false</c></returns> /// ------------------------------------------------------------------------------------ private bool HandleBackspaceAfterEmptySectionHeadParagraph(SelectionHelper helper) { ILocationTracker tracker = ((ITeView)Control).LocationTracker; SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top); ScrBook book = new ScrBook(m_cache, tracker.GetBookHvo(helper, SelectionHelper.SelLimitType.Top)); ScrSection section = new ScrSection(m_cache, tracker.GetSectionHvo(helper, SelectionHelper.SelLimitType.Top)); int iSection = tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top); int cParas = section.HeadingOA != null ? section.HeadingOA.ParagraphsOS.Count : 0; if (cParas > 0) { // If we are the beginning of content before a multi-paragraph heading // and the last paragraph is empty, we delete the last paragraph of // the heading. if (cParas > 1) { StTxtPara para = (StTxtPara)section.HeadingOA.ParagraphsOS[cParas - 1]; if (para.Contents.Length == 0) { section.HeadingOA.ParagraphsOS.RemoveAt(cParas - 1); return true; } } // If we are at beginning of content before an empty section head and // not in the first section, we should merge sections. else if (iSection > 0) { StTxtPara para = (StTxtPara)section.HeadingOA.ParagraphsOS[cParas - 1]; if (para.Contents.Length == 0) { return MergeWithPreviousSectionIfInSameContext(helper, book, section, iSection, false); } } return false; // heading is not empty } // don't crash if database is corrupt - allow user to merge with // previous section (TE-4869) if (iSection > 0) { return MergeWithPreviousSectionIfInSameContext(helper, book, section, iSection, false); } return false; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Merges the content of the current section with the previous section if in the /// sections have the same context. /// </summary> /// <param name="helper">The selection helper.</param> /// <param name="book">The current book.</param> /// <param name="section">The current section.</param> /// <param name="iSection">The index of the current section.</param> /// <param name="fPositionAtEnd">If true position of Selection is placed at end of /// paragraph, else at the beginning.</param> /// <returns><c>true</c> if we merged the sections, otherwise <c>false</c>.</returns> /// ------------------------------------------------------------------------------------ private bool MergeWithPreviousSectionIfInSameContext(SelectionHelper helper, ScrBook book, IScrSection section, int iSection, bool fPositionAtEnd) { IScrSection prevSection = book.SectionsOS[iSection - 1]; if (SectionsHaveSameContext(prevSection, section)) { MergeContentWithPreviousSection(helper, book, section, iSection, fPositionAtEnd); return true; } return false; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Apply style to selection /// </summary> /// ------------------------------------------------------------------------------------ public override void ApplyStyle(string sStyleToApply) { CheckDisposed(); // Make sure that the Chapter Number style is not applied to non-numeric data if (sStyleToApply == ScrStyleNames.ChapterNumber && CurrentSelection != null) { ITsString tssSelected; CurrentSelection.Selection.GetSelectionString(out tssSelected, string.Empty); if (tssSelected.Text != null) { foreach (char ch in tssSelected.Text) { if (!Char.IsDigit(ch)) { MiscUtils.ErrorBeep(); return; } } } } base.ApplyStyle(sStyleToApply); // Update the footnote markers if we changed the style of a footnote if ((sStyleToApply == ScrStyleNames.CrossRefFootnoteParagraph || sStyleToApply == ScrStyleNames.NormalFootnoteParagraph) && ParagraphHvo > 0) { // Save the selection SelectionHelper prevSelection = CurrentSelection; if (m_cache.MarkerIndexCache != null) m_cache.MarkerIndexCache.ClearCache(); StTxtPara para = new StTxtPara(m_cache, ParagraphHvo); Debug.Assert(m_cache.GetClassOfObject(para.OwnerHVO) == StFootnote.kClassId); StFootnote footnote = new StFootnote(m_cache, para.OwnerHVO); ScrBook book = new ScrBook(m_cache, footnote.OwnerHVO); m_cache.PropChanged(null, PropChangeType.kpctNotifyAll, book.Hvo, (int)ScrBook.ScrBookTags.kflidFootnotes, 0, book.FootnotesOS.Count, book.FootnotesOS.Count); // restore the selection prevSelection.SetSelection(true); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Merges the section the with following section if they are in the same context. /// </summary> /// <param name="helper">The selection helper.</param> /// <param name="book">The book.</param> /// <param name="iSection">The index of the current section.</param> /// <param name="section">The current section.</param> /// <param name="fDeleteForward">if set to <c>true</c> the user pressed the delete key, /// otherwise the backspace key.</param> /// <returns><c>true</c> if we merged the sections, otherwise <c>false</c>.</returns> /// ------------------------------------------------------------------------------------ private bool MergeWithFollowingSectionIfInSameContext(SelectionHelper helper, ScrBook book, int iSection, IScrSection section, bool fDeleteForward) { IScrSection nextSection = book.SectionsOS[iSection + 1]; // Merge the sections if they have the same context. if (SectionsHaveSameContext(nextSection, section)) { bool wasInHeading = InSectionHead; int lastParaIndex = section.HeadingOA.ParagraphsOS.Count - 1; MergeHeadingWithFollowingSection(helper, book, section, iSection); // Now we have to re-establish a selection if (wasInHeading && fDeleteForward) { // delete key was pressed at end of section head, place IP at // end of what was the original heading section = book.SectionsOS[iSection]; StTxtPara lastPara = (StTxtPara)section.HeadingOA.ParagraphsOS[lastParaIndex]; SetInsertionPoint((int)ScrSection.ScrSectionTags.kflidHeading, BookFilter.GetBookIndex(book.Hvo), iSection, lastParaIndex); CurrentSelection.IchAnchor = lastPara.Contents.Length; CurrentSelection.SetSelection(true); } else { // delete key was pressed in empty section content, place IP // at beginning of what was following section heading SetInsertionPoint((int)ScrSection.ScrSectionTags.kflidHeading, BookFilter.GetBookIndex(book.Hvo), iSection, lastParaIndex + 1); } return true; } return false; }
///// ------------------------------------------------------------------------------------ ///// <summary> ///// Goes to the closest match in the given section or following section starting at the ///// given paragraph and character offsets and ending at the given paragraph and character ///// offsets ///// </summary> ///// <param name="targetRef">ScrReference to find</param> ///// <param name="bookIndex">index of book to look in</param> ///// <param name="section">section to search</param> ///// <param name="startingParaIndex">starting paragraph to look in</param> ///// <param name="startingCharIndex">starting character index to look at</param> ///// <param name="endingParaIndex">last paragraph to look in (-1 for end)</param> ///// <param name="endingCharIndex">ending character index to look at (-1 for end)</param> ///// <returns><c>false</c> if we can't go to the closest match </returns> ///// ------------------------------------------------------------------------------------ //protected virtual bool GotoClosestMatch(ScrReference targetRef, // int bookIndex, ScrSection section, int startingParaIndex, int startingCharIndex, // int endingParaIndex, int endingCharIndex) //{ // int paraCount = section.ContentParagraphCount; // if (startingParaIndex >= paraCount) // return false; // if (endingParaIndex == -1) // endingParaIndex = paraCount - 1; // if (endingCharIndex == -1) // endingCharIndex = section.LastContentParagraph.Contents.Length; // // only process this section if we have content to check // if (startingParaIndex == endingParaIndex && startingCharIndex == endingCharIndex) // return false; // // Indicator to look for the min of a section. // bool findMin = false; // // If the section does not contain this reference, then look to see if we want to // // put the selection between this section and the next one. // if (!section.ContainsReference(targetRef)) // { // // If there is no previous section and the reference is less than the // // min of this section, then place the IP at the start of this section // if (section.VerseRefMin > targetRef && section.PreviousSection == null) // { // SetInsertionPoint((int)ScrSection.ScrSectionTags.kflidContent, // bookIndex, section.IndexInBook, 0, 0, true, VwScrollSelOpts.kssoNearTop); // return true; // } // ScrSection nextSection = section.NextSection; // if (nextSection == null) // { // // If there is no following section and the reference is larger then the // // max of this section, then place it at the end of this section // if (section.VerseRefMax <= targetRef) // { // SetIpAtEndOfSection(bookIndex, section); // return true; // } // else // return false; // } // // If the reference falls between the max of this section and the max of the next // // section, then the IP will either be at the end of this section or in the next section. // if (section.VerseRefMax <= targetRef && targetRef <= nextSection.VerseRefMax) // { // // If the reference falls between the two sections, then place it at the edge of the section // // that has a reference closest to the target reference. // if (targetRef <= nextSection.VerseRefMin || section.VerseRefEnd > nextSection.VerseRefStart) // { // if (targetRef.ClosestTo(section.VerseRefMax, nextSection.VerseRefMin) == 0) // { // // set selection to the end of this section // SetInsertionPoint((int)ScrSection.ScrSectionTags.kflidContent, // bookIndex, section.IndexInBook, paraCount - 1, // section.LastContentParagraph.Contents.Length, true, // VwScrollSelOpts.kssoNearTop); // return true; // } // else // { // // Place the selection at the min reference of the next section, so // // set the target reference to the min reference so it will be // // found below. // targetRef.BBCCCVVV = nextSection.VerseRefMin; // findMin = true; // } // } // section = nextSection; // // reset index limits for changed section // paraCount = section.ContentParagraphCount; // startingParaIndex = 0; // endingParaIndex = paraCount - 1; // endingCharIndex = startingCharIndex = -1; // ADDED 8-7-2008 TLB // } // else // return false; // } // ScrVerse prevVerse = null; // REVIEW: This might need to go outside this for loop // // The reference goes somewhere in this section, so look for the spot to put it // for (int paraIndex = startingParaIndex; paraIndex <= endingParaIndex; ++paraIndex) // { // ScrTxtPara para = new ScrTxtPara(m_cache, section[paraIndex].Hvo); // ScrVerseSet verseSet = new ScrVerseSet(para); // int currentEndingCharIndex = (paraIndex == endingParaIndex && endingCharIndex != -1)? endingCharIndex: para.Contents.Length - 1; // foreach (ScrVerse verse in verseSet) // { // if (verse.VerseStartIndex >= currentEndingCharIndex) // past the end // break; // // If we haven't gotten to the beginning position where we want to start // // looking or we're looking for the minimum reference in the section, and // // this is not it, then continue looking. // if (verse.VerseStartIndex >= startingCharIndex || // (findMin && verse.StartRef == section.VerseRefMin)) // { // // When the target reference is found, set the IP // if (verse.StartRef >= targetRef) // { // // REVIEW: what to do when prevVerse is null // int ich = verse.VerseStartIndex; // if (verse.StartRef > targetRef && prevVerse != null) // { // ich = prevVerse.TextStartIndex; // if (prevVerse.HvoPara != para.Hvo) // paraIndex--; // } // // set the IP here now // GoToPosition(targetRef, bookIndex, section, paraIndex, ich); // return true; // } // } // prevVerse = verse; // } // // after the first paragraph, start looking at 0 // startingCharIndex = 0; // } // return false; //} /// ------------------------------------------------------------------------------------ /// <summary> /// Goes to the closest match in the given book. /// </summary> /// <param name="targetRef">ScrReference to find</param> /// <param name="book">index of book to look in</param> /// <returns><c>false</c> if we can't go to the closest match </returns> /// ------------------------------------------------------------------------------------ protected virtual void GotoClosestPrecedingRef(ScrReference targetRef, ScrBook book) { Debug.Assert(book != null); Debug.Assert(book.SectionsOS.Count > 0); ScrSection section = null; // Move backward through the sections in the book to find the one // whose start reference is less than the one we're looking for. for (int iSection = book.SectionsOS.Count - 1; iSection >= 0; iSection--) { section = book[iSection]; // If the reference we're looking for is greater than the current // section's start reference, then get out of the loop because we've // found the section in which we need to place the IP. if (targetRef >= section.VerseRefStart) break; } // At this point, we know we have the section in which we think the // IP should be located. int iBook = BookFilter.GetBookIndex(book.Hvo); // If the reference we're looking for is before the section's start reference, // then we need to put the IP at the beginning of the book's first section, // but after a chapter number if the sections begins with one. if (targetRef < section.VerseRefStart) { GoToFirstChapterInSection(iBook, section); return; } int paraCount = section.ContentParagraphCount; // If there are no paragraphs in the section, then we're out of luck. Debug.Assert(paraCount > 0); // Go through the paragraphs and find the one in which we // think the IP should be located. for (int iPara = paraCount - 1; iPara >= 0; iPara--) { ScrTxtPara para = new ScrTxtPara(m_cache, section[iPara].Hvo); ScrVerseList verses = new ScrVerseList(para); // Go backward through the verses in the paragrah, looking for the // first one that is less than the reference we're looking for. for (int iVerse = verses.Count - 1; iVerse >= 0; iVerse--) { // If the current reference is before (i.e. less) the one we're looking // for, then put the IP right after the it's verse number. if (verses[iVerse].StartRef <= targetRef) { GoToPosition(targetRef, iBook, section, iPara, verses[iVerse].TextStartIndex); return; } } } // At this point, we have failed to find a good location for the IP. // Therefore, just place it at the beginning of the section. GoToSectionStart(iBook, section.IndexInBook); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Deletes a section heading. /// </summary> /// <param name="helper">Selection information</param> /// <param name="allowHeadingText">if <code>true</code> section head will be deleted /// even if heading contains text</param> /// <param name="positionAtEnd">if <code>true</code> IP will be at end of paragraph /// before top point of current selection</param> /// <returns><code>true</code> if deletion was done</returns> /// ------------------------------------------------------------------------------------ private bool DeleteSectionHead(SelectionHelper helper, bool allowHeadingText, bool positionAtEnd) { ILocationTracker tracker = ((ITeView)Control).LocationTracker; if (helper.GetNumberOfLevels(SelectionHelper.SelLimitType.Top) != tracker.GetLevelCount((int)ScrSection.ScrSectionTags.kflidContent)) return false; int tag = helper.GetTextPropId(SelectionHelper.SelLimitType.Top); if (tag != (int)StTxtPara.StTxtParaTags.kflidContents && tag != SimpleRootSite.kTagUserPrompt) { // Currently this is the only possible leaf property in draft view; // if this changes somehow, we'll probably need to enhance this code. Debug.Assert(false); return false; } int hvoBook = tracker.GetBookHvo(helper, SelectionHelper.SelLimitType.Top); if (hvoBook < 0) { Debug.Assert(false); return false; } ScrBook book = new ScrBook(m_cache, hvoBook); int iSection = tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top); if (iSection < 0) { // Something changed catastrophically. Book has something in it other than sections. Debug.Assert(false); return false; } IScrSection section = book.SectionsOS[iSection]; if (helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[0].tag != (int)StText.StTextTags.kflidParagraphs) { // Something changed catastrophically. StText has something in it other than paragraphs! Debug.Assert(false); return false; } // For now we just handle the heading. if (helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[1].tag != (int)ScrSection.ScrSectionTags.kflidHeading) { // Add code here if desired to handle bsp/del at boundary of body. return false; } // OK, we're dealing with a change at the boundary of a section heading // (in a paragraph of an StText that is the heading of an ScrSection in an ScrBook). IStText text = section.HeadingOA; int ihvoPara = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[0].ihvo; IStTxtPara para = (IStTxtPara)(text.ParagraphsOS[ihvoPara]); if (!allowHeadingText && para.Contents.Length > 0) { // The current heading paragraph has something in it! // For now we won't try to handle this. // (The problem is knowing what to do with the undeleted header text... // make it part of the previous section? The previous header? Delete it?) return false; } if (text.ParagraphsOS.Count != 1) { // Backspace at start or delete at end of non-empty section, and the paragraph is // empty. Do nothing. return false; // Other options: // - delete the section? But what do we do with the rest of its heading? // - delete the empty paragraph? That's easy...just // text.ParagraphsOS.RemoveAt(ihvoPara); // But where do we put the IP afterwards? At the end of the previous body, // for bsp, or the start of our own body, for del? Or keep it in the heading? } // OK, we're in a completely empty section heading. // If it's the very first section of the book, we can't join it to the previous // section, so do nothing. (May eventually enhance to join the two books... // perhaps after asking for confirmation!) if (iSection == 0) return false; // Finally...we know we're going to merge the two sections. MergeContentWithPreviousSection(helper, book, section, iSection, positionAtEnd); return true; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Inserts one or more paragraphs at the end of a section. New sections for the book /// may also be created. /// </summary> /// <param name="book"></param> /// <param name="section"></param> /// <param name="ttpSrcArray">Array of props of each para to be inserted</param> /// <param name="tssParas">Array of TsStrings for each para to be inserted</param> /// <param name="sectionIndex"></param> /// <param name="cAddedSections"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private bool InsertParagraphsAtSectionEnd(ScrBook book, IScrSection section, ITsTextProps[] ttpSrcArray, ITsString[] tssParas, int sectionIndex, out int cAddedSections) { cAddedSections = 0; bool isIntro = false; for (int i = 0; i < ttpSrcArray.Length; i++) { IStStyle style = m_scr.FindStyle(ttpSrcArray[i]); if (style.Structure == StructureValues.Heading) { // If content has been added to section, create a new section. Otherwise, // add the new paragraph to the end of the current section heading. if (section.ContentOA.ParagraphsOS.Count > 0) { isIntro = (style.Context == ContextValues.Intro); // Create a new section and add the current paragraph to the heading section = ScrSection.CreateEmptySection(book, sectionIndex + cAddedSections); CreateParagraph(section.HeadingOA, -1, ttpSrcArray[i], tssParas[i]); // Need additional prop changed event to get screen to refresh properly m_cache.PropChanged(null, PropChangeType.kpctNotifyAll, book.Hvo, (int)ScrBook.ScrBookTags.kflidSections, sectionIndex + cAddedSections, 1, 0); cAddedSections++; } else { // Create heading paragraph at end of section heading CreateParagraph(section.HeadingOA, -1, ttpSrcArray[i], tssParas[i]); } } else { // Create content paragraph for the current section CreateParagraph(section.ContentOA, -1, ttpSrcArray[i], tssParas[i]); } } // create an empty paragraph if section content is empty if (section.ContentOA.ParagraphsOS.Count == 0) { string styleName = isIntro ? ScrStyleNames.IntroParagraph : ScrStyleNames.NormalParagraph; StTxtParaBldr bldr = new StTxtParaBldr(m_cache); bldr.ParaProps = StyleUtils.ParaStyleTextProps(styleName); ITsTextProps charProps = StyleUtils.CharStyleTextProps(styleName, m_cache.DefaultVernWs); bldr.AppendRun(string.Empty, charProps); bldr.CreateParagraph(section.ContentOAHvo); } return true; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Merges heading of given section into the heading of the follwing section and then /// deletes the given section. We assume that the content of the current section is /// empty. /// </summary> /// <param name="helper"> </param> /// <param name="book"></param> /// <param name="section"></param> /// <param name="ihvoSection"></param> /// ------------------------------------------------------------------------------------ private void MergeHeadingWithFollowingSection(SelectionHelper helper, ScrBook book, IScrSection section, int ihvoSection) { // Get the following section and move the paragraphs. IScrSection sectionNext = book.SectionsOS[ihvoSection + 1]; IStText textNext = sectionNext.HeadingOA; if (textNext == null) { // Prevent crash when dealing with corrupt database (TE-4869) // Since the next section doesn't have a heading text, we simply move the entire // text object from the current section head to the next section. m_cache.ChangeOwner(section.HeadingOAHvo, sectionNext.Hvo, (int)ScrSection.ScrSectionTags.kflidHeading); } else { IStText textOldHeading = section.HeadingOA; int cOldHeadingParas = textOldHeading.ParagraphsOS.Count; m_cache.MoveOwningSequence(textOldHeading.Hvo, (int)StText.StTextTags.kflidParagraphs, 0, cOldHeadingParas - 1, textNext.Hvo, (int)StText.StTextTags.kflidParagraphs, 0); } // protected for some reason...textNext.ParagraphsOS.Append(text.ParagraphsOS.HvoArray); book.SectionsOS.RemoveAt(ihvoSection); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Insert a new section at the given position. The new section will include an empty /// paragraph. /// </summary> /// <param name="book"></param> /// <param name="iSection"></param> /// <param name="isIntroSection"></param> /// ------------------------------------------------------------------------------------ protected internal IScrSection InsertSectionAtIndex(ScrBook book, int iSection, bool isIntroSection) { if (m_cache == null) return null; return ScrSection.CreateSectionWithEmptyParas(book, iSection, isIntroSection); }
public void MergeBTsWhenParasMerge_FirstParaHasNoBt_DelKey() { CheckDisposed(); ShowForm(Lng.English, DummyBasicViewVc.DisplayType.kNormal); IVwRootBox rootBox = m_basicView.RootBox; // Add a second paragraph to the first text and create a Back Translations on // only the second paragraph ScrBook book = new ScrBook(Cache, m_hvoRoot); StText text1 = (StText)book.FootnotesOS[0]; StTxtPara para1 = (StTxtPara)text1.ParagraphsOS[0]; StTxtPara para2 = m_scrInMemoryCache.AddParaToMockedText(text1.Hvo, string.Empty); m_scrInMemoryCache.AddRunToMockedPara(para2, DummyBasicView.kSecondParaEng, m_wsEng); // We'll just re-use our "vernacular" WS for the back translation, for testing purposes. ICmTranslation trans2 = m_inMemoryCache.AddBtToMockedParagraph(para2, m_wsEng); m_inMemoryCache.AddRunToMockedTrans(trans2, m_wsEng, "BT2", null); Cache.PropChanged(null, PropChangeType.kpctNotifyAll, text1.Hvo, (int)StText.StTextTags.kflidParagraphs, 1, 1, 0); // Make a selection from the end of first paragraph to the beginning of the second. SelLevInfo[] levelInfo = new SelLevInfo[2]; levelInfo[1].tag = m_flidContainingTexts; levelInfo[1].cpropPrevious = 0; levelInfo[1].ihvo = 0; levelInfo[0].tag = (int)StText.StTextTags.kflidParagraphs; levelInfo[0].cpropPrevious = 0; levelInfo[0].ihvo = 0; int ich = DummyBasicView.kFirstParaEng.Length; rootBox.MakeTextSelection(0, 2, levelInfo, (int)StTxtPara.StTxtParaTags.kflidContents, 0, ich, 0, 0, true, 1, null, true); TypeDelete(); Assert.AreEqual(DummyBasicView.kFirstParaEng + DummyBasicView.kSecondParaEng, para1.Contents.Text); IEnumerator<ICmTranslation> translations = para1.TranslationsOC.GetEnumerator(); translations.MoveNext(); ICmTranslation transl = translations.Current; Assert.AreEqual("BT2", transl.Translation.GetAlternative(m_wsEng).Text); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Merges the paras in table. /// </summary> /// <param name="helper">The helper.</param> /// <param name="dpt">The problem deletion type.</param> /// <returns><c>true</c> if we merged the paras, otherwise <c>false</c>.</returns> /// ------------------------------------------------------------------------------------ internal protected bool MergeParasInTable(SelectionHelper helper, VwDelProbType dpt) { SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top); if (levInfo[0].tag != (int)StText.StTextTags.kflidParagraphs) return false; ILocationTracker tracker = ((ITeView)Control).LocationTracker; IScrBook book = new ScrBook(m_cache, tracker.GetBookHvo( helper, SelectionHelper.SelLimitType.Anchor)); SelLevInfo tmpInfo; IStText text; if (helper.GetLevelInfoForTag((int)ScrBook.ScrBookTags.kflidTitle, out tmpInfo)) text = book.TitleOA; else { IScrSection section = book.SectionsOS[tracker.GetSectionIndexInBook( helper, SelectionHelper.SelLimitType.Anchor)]; text = (levInfo[1].tag == (int)ScrSection.ScrSectionTags.kflidHeading ? section.HeadingOA : text = section.ContentOA); } int iPara = helper.GetLevelInfoForTag((int)StText.StTextTags.kflidParagraphs).ihvo; StTxtPara currPara = (StTxtPara)text.ParagraphsOS[iPara]; ITsStrBldr bldr; // Backspace at beginning of paragraph if (dpt == VwDelProbType.kdptBsAtStartPara) { if (iPara <= 0) { MiscUtils.ErrorBeep(); return false; } StTxtPara prevPara = (StTxtPara)text.ParagraphsOS[iPara - 1]; int prevParaLen = prevPara.Contents.Length; // Need to make sure we move the back translations AboutToDelete(helper, currPara.Hvo, text.Hvo, (int)StText.StTextTags.kflidParagraphs, iPara, false); bldr = prevPara.Contents.UnderlyingTsString.GetBldr(); bldr.ReplaceTsString(prevPara.Contents.Length, prevPara.Contents.Length, currPara.Contents.UnderlyingTsString); prevPara.Contents.UnderlyingTsString = bldr.GetString(); text.ParagraphsOS.RemoveAt(iPara); helper.SetIch(SelectionHelper.SelLimitType.Top, prevParaLen); helper.SetIch(SelectionHelper.SelLimitType.Bottom, prevParaLen); levInfo[0].ihvo = iPara - 1; helper.SetLevelInfo(SelectionHelper.SelLimitType.Top, levInfo); helper.SetLevelInfo(SelectionHelper.SelLimitType.Bottom, levInfo); helper.SetSelection(true); return true; } // delete at end of a paragraph int cParas = text.ParagraphsOS.Count; if (iPara + 1 >= cParas) return false; // We don't handle merging across StTexts StTxtPara nextPara = (StTxtPara)text.ParagraphsOS[iPara + 1]; // Need to make sure we move the back translations AboutToDelete(helper, nextPara.Hvo, text.Hvo, (int)StText.StTextTags.kflidParagraphs, iPara + 1, false); bldr = currPara.Contents.UnderlyingTsString.GetBldr(); bldr.ReplaceTsString(currPara.Contents.Length, currPara.Contents.Length, nextPara.Contents.UnderlyingTsString); currPara.Contents.UnderlyingTsString = bldr.GetString(); text.ParagraphsOS.RemoveAt(iPara + 1); helper.SetSelection(true); return true; }
public void AdjustAnnotationReferences_ParaInArchive() { IScrBook genesis = m_scrInMemoryCache.AddBookToMockedScripture(1, "Genesis"); StText titleText = m_scrInMemoryCache.AddTitleToMockedBook(genesis.Hvo, "Genesis"); IStPara titlePara = titleText.ParagraphsOS[0]; // Introduction section IScrSection section = m_scrInMemoryCache.AddSectionToMockedBook(genesis.Hvo); m_scrInMemoryCache.AddSectionHeadParaToSection(section.Hvo, "Introduction head", ScrStyleNames.IntroSectionHead); StTxtPara para = m_scrInMemoryCache.AddParaToMockedSectionContent(section.Hvo, ScrStyleNames.IntroParagraph); m_scrInMemoryCache.AddRunToMockedPara(para, "An intro to Genesis", null); section.AdjustReferences(true); IScrDraft version = new ScrDraft(); m_scr.ArchivedDraftsOC.Add(version); int hvoSavedVersion = m_scr.AddBookToSavedVersion(version, genesis.Hvo); IScrBook genesisSaved = new ScrBook(m_scrInMemoryCache.Cache, hvoSavedVersion); IStPara paraSaved = genesisSaved.SectionsOS[0].ContentOA.ParagraphsOS[0]; ScrBookAnnotations annotations = (ScrBookAnnotations)m_scr.BookAnnotationsOS[0]; BCVRef ref1 = new BCVRef(1, 1, 0); IScrScriptureNote note = annotations.InsertNote(ref1, ref1, paraSaved, paraSaved, LangProject.kguidAnnConsultantNote); Assert.IsNotNull(note); m_scr.AdjustAnnotationReferences(); Assert.AreEqual(para.Hvo, note.BeginObjectRA.Hvo); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determines if the selection is an entire book /// </summary> /// <param name="helper"></param> /// <param name="topInfo"></param> /// <param name="bottomInfo"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private bool IsBookSelection (SelectionHelper helper, SelLevInfo[] topInfo, SelLevInfo[] bottomInfo) { ILocationTracker tracker = ((ITeView)Control).LocationTracker; int bookTitleLevelCount = tracker.GetLevelCount((int)ScrBook.ScrBookTags.kflidTitle); if (topInfo.Length == bookTitleLevelCount && bottomInfo.Length == bookTitleLevelCount) { // Verify that selection goes from beginning of book title to // beginning of title in next book. return (tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Top) == tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Bottom) - 1 && topInfo[1].tag == (int)ScrBook.ScrBookTags.kflidTitle && topInfo[1].ihvo == 0 && topInfo[0].tag == (int)StText.StTextTags.kflidParagraphs && topInfo[0].ihvo == 0 && bottomInfo[1].tag == (int)ScrBook.ScrBookTags.kflidTitle && bottomInfo[1].ihvo == 0 && bottomInfo[0].tag == (int)StText.StTextTags.kflidParagraphs && bottomInfo[0].ihvo == 0 && helper.IchAnchor == 0 && helper.IchEnd == 0); } else if (topInfo.Length == bookTitleLevelCount && bottomInfo.Length == tracker.GetLevelCount((int)ScrSection.ScrSectionTags.kflidContent)) { // Check that selection is at start of title bool bookSel = (tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Top) == tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Bottom) && topInfo[1].tag == (int)ScrBook.ScrBookTags.kflidTitle && topInfo[1].ihvo == 0 && topInfo[0].tag == (int)StText.StTextTags.kflidParagraphs && topInfo[0].ihvo == 0 && helper.GetIch(SelectionHelper.SelLimitType.Top) == 0); if (bookSel) { // Get information about last paragraph of the book ScrBook book = new ScrBook(m_cache, tracker.GetBookHvo(helper, SelectionHelper.SelLimitType.Top)); int iSection = book.SectionsOS.Count - 1; IScrSection section = book.SectionsOS[iSection]; int iPara = section.ContentOA.ParagraphsOS.Count - 1; StTxtPara para = (StTxtPara) section.ContentOA.ParagraphsOS[iPara]; int ichEnd = para.Contents.Length; // Check that selection is at end of last paragraph of book bookSel = (tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Bottom) == iSection && bottomInfo[1].tag == (int)ScrSection.ScrSectionTags.kflidContent && bottomInfo[0].ihvo == iPara && bottomInfo[0].tag == (int)StText.StTextTags.kflidParagraphs && helper.GetIch(SelectionHelper.SelLimitType.Bottom) == ichEnd); } return bookSel; } return false; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Handles deletion of empty section heading paragraph on delete key being pressed at /// text boundary. /// </summary> /// <param name="helper"></param> /// <returns><c>true</c> if we handled the deletion, otherwise <c>false</c></returns> /// ------------------------------------------------------------------------------------ private bool HandleDeleteBeforeEmptySectionHeadParagraph(SelectionHelper helper) { SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top); ScrBook book = new ScrBook(m_cache, ((ITeView)Control).LocationTracker.GetBookHvo( helper, SelectionHelper.SelLimitType.Top)); // Delete problem deletion will be at end of last paragraph of content, // need to check following section head (if available) // Get next section of book. int iSection = ((ITeView)Control).LocationTracker.GetSectionIndexInBook( helper, SelectionHelper.SelLimitType.Top); bool positionAtEnd = false; if (!InSectionHead) { iSection++; if (iSection > book.SectionsOS.Count - 1) return false; positionAtEnd = true; } else if (iSection == 0) return false; IScrSection section = book.SectionsOS[iSection]; if (section.HeadingOA == null || section.HeadingOA.ParagraphsOS.Count == 0) { // don't crash if database is corrupt - allow user to merge the two // sections (TE-4869) return MergeWithPreviousSectionIfInSameContext(helper, book, section, iSection, positionAtEnd); } else { // if there are more than one paragraph in heading, check to see if first // paragraph can be deleted. if (section.HeadingOA.ParagraphsOS.Count > 1) { StTxtPara para = (StTxtPara)section.HeadingOA.ParagraphsOS[0]; if (para.Contents.Length == 0) { section.HeadingOA.ParagraphsOS.RemoveAt(0); return true; } } // If we are at end of content before an empty section head, // we should merge sections. else { StTxtPara para = (StTxtPara)section.HeadingOA.ParagraphsOS[0]; if (para.Contents.Length == 0) { return MergeWithPreviousSectionIfInSameContext(helper, book, section, iSection, positionAtEnd); } } } return false; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Finds the previous footnote and returns it. /// </summary> /// <param name="para">Paragraph to start search</param> /// <param name="ich">Character index to start search, or -1 to start at the end of /// the paragraph.</param> /// <returns>Previous footnote, or <c>null</c> if there isn't a previous footnote in the /// current book.</returns> /// ------------------------------------------------------------------------------------ public static ScrFootnote FindPreviousFootnote(IStTxtPara para, int ich) { FdoCache cache = para.Cache; IScrBook book; IStText text = new StText(cache, para.OwnerHVO); int iPara = Array.IndexOf(text.ParagraphsOS.HvoArray, para.Hvo); int flid = text.OwningFlid; if (flid == (int)ScrSection.ScrSectionTags.kflidHeading || flid == (int)ScrSection.ScrSectionTags.kflidContent) { ScrSection section = new ScrSection(cache, text.OwnerHVO); int iSection = section.IndexInBook; return ScrFootnote.FindPreviousFootnote(cache, section.OwningBook, ref iSection, ref iPara, ref ich, ref flid); } else if (flid == (int)ScrBook.ScrBookTags.kflidTitle) { book = new ScrBook(cache, text.OwnerHVO); return ScrFootnote.FindPreviousFootnoteInText(text, ref iPara, ref ich, false); } else throw new Exception("Can only create footnotes in Scripture Book titles, section heads, and contents"); }