/// ------------------------------------------------------------------------------------ /// <summary> /// Implement CreateTestData, called by InMemoryFdoTestBase set up. /// </summary> /// ------------------------------------------------------------------------------------ protected override void CreateTestData() { m_mockedChooserDlg = new DynamicMock(typeof(ICmPossibilitySupplier)); m_mockedDataAccess = new DynamicMock(typeof(IVwCacheDa)); m_scrInMemoryCache.InitializeAnnotationDefs(); m_scrInMemoryCache.InitializeScrAnnotationCategories(); CreateTestUserView(); // Create some Scripture annotations m_annotationsGen = (ScrBookAnnotations)m_scr.BookAnnotationsOS[0]; ScrReference ref1 = new ScrReference(1, 1, 1, Paratext.ScrVers.English); ScrReference ref2 = new ScrReference(1, 1, 2, Paratext.ScrVers.English); ScrReference ref3 = new ScrReference(1, 1, 3, Paratext.ScrVers.English); // Insert notes for Genesis 1:1, 1:2, and 1:3 m_note1 = m_annotationsGen.InsertNote(ref1, ref1, null, null, LangProject.kguidAnnConsultantNote); m_note2a = m_annotationsGen.InsertNote(ref2, ref2, null, null, LangProject.kguidAnnConsultantNote); m_note2b = m_annotationsGen.InsertNote(ref2, ref2, null, null, LangProject.kguidAnnConsultantNote); m_note3 = m_annotationsGen.InsertNote(ref3, ref3, null, null, LangProject.kguidAnnConsultantNote); m_note1.AnnotationTypeRA = m_inMemoryCache.m_consultantNoteDefn; m_note2a.AnnotationTypeRA = m_inMemoryCache.m_consultantNoteDefn; m_note2b.AnnotationTypeRA = m_inMemoryCache.m_translatorNoteDefn; m_note3.AnnotationTypeRA = m_inMemoryCache.m_translatorNoteDefn; m_note1.ResolutionStatus = NoteStatus.Open; m_note2a.ResolutionStatus = NoteStatus.Closed; m_note2b.ResolutionStatus = NoteStatus.Open; m_note3.ResolutionStatus = NoteStatus.Closed; m_note1.CategoriesRS.Append(m_inMemoryCache.m_categoryDiscourse); m_note2a.CategoriesRS.Append(m_inMemoryCache.m_categoryGrammar); m_note2b.CategoriesRS.Append(m_inMemoryCache.m_categoryGrammar_PronominalRef); m_note3.CategoriesRS.Append(m_inMemoryCache.m_categoryGrammar_PronominalRef_ExtendedUse); m_note3.CategoriesRS.Append(m_inMemoryCache.m_categoryDiscourse); // This note has 2 categories }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determines whether this reference range overlaps the range specified by the given /// start and end reference /// </summary> /// <param name="start">Start reference</param> /// <param name="end">End Reference</param> /// <returns>true if there is any overlap</returns> /// ------------------------------------------------------------------------------------ public bool OverlapsRange(ScrReference start, ScrReference end) { // If the book number is completely contained by the start and end reference // then it definitely overlaps. if (Book > start.Book && Book < end.Book) return true; int startChapter, endChapter; if (Book == start.Book) { startChapter = start.Chapter; endChapter = (start.Book == end.Book) ? end.Chapter : start.LastChapter; } else if (Book == end.Book) { startChapter = 1; endChapter = end.Chapter; } else return false; return (StartChapter <= endChapter && EndChapter >= startChapter); }
public void ValidScrReferences() { ScrReference bcvRef = new ScrReference(1, 2, 3, ScrVers.English); Assert.IsTrue(bcvRef.Valid); Assert.IsFalse(bcvRef.IsBookTitle); Assert.AreEqual(1002003, (int)bcvRef); Assert.AreEqual(1, bcvRef.Book); Assert.AreEqual(2, bcvRef.Chapter); Assert.AreEqual(3, bcvRef.Verse); Assert.AreEqual(ScrVers.English, bcvRef.Versification); bcvRef = new ScrReference(4005006, ScrVers.Original); Assert.IsTrue(bcvRef.Valid); Assert.IsFalse(bcvRef.IsBookTitle); Assert.AreEqual(4005006, (int)bcvRef); Assert.AreEqual(4, bcvRef.Book); Assert.AreEqual(5, bcvRef.Chapter); Assert.AreEqual(6, bcvRef.Verse); Assert.AreEqual(ScrVers.Original, bcvRef.Versification); bcvRef = new ScrReference(); Assert.IsFalse(bcvRef.Valid); Assert.IsFalse(bcvRef.IsBookTitle); Assert.AreEqual(0, (int)bcvRef); Assert.AreEqual(0, bcvRef.Book); Assert.AreEqual(0, bcvRef.Chapter); Assert.AreEqual(0, bcvRef.Verse); bcvRef = new ScrReference(5, 0, 0, ScrVers.English); Assert.IsFalse(bcvRef.Valid); Assert.IsTrue(bcvRef.IsBookTitle); Assert.AreEqual(5000000, (int)bcvRef); Assert.AreEqual(5, bcvRef.Book); Assert.AreEqual(0, bcvRef.Chapter); Assert.AreEqual(0, bcvRef.Verse); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Navigate to the beginning of the text of the first (implicit or explicit) chapter /// in the first paragraph in the specified scripture section. If a chapter isn't /// found then the IP is put at the beginning of the content paragraph. /// </summary> /// <param name="iBook">0-based index of the book (in this view)</param> /// <param name="section">The section (in the given book, as displayed in this view) /// </param> /// ------------------------------------------------------------------------------------ private void GoToFirstChapterInSection(int iBook, ScrSection section) { int ichChapterStart = 0; ScrVerseSet verseSet = new ScrVerseSet(new ScrTxtPara(m_cache, section[0].Hvo)); if (verseSet.MoveNext()) { ScrVerse verse = (ScrVerse)verseSet.Current; if (!verse.VerseNumberRun) ichChapterStart = verse.TextStartIndex; } ScrReference scrRef = new ScrReference(section.VerseRefStart, m_scr.Versification); GoToPosition(scrRef, iBook, section, 0, ichChapterStart); }
// This is the start of an alternative implementation of GotoVerseBtSeg, actually searching the text. //BCVRef m_startRef; //BCVRef m_endRef; //para.GetBCVRefAtPosition(0, out m_startRef, out m_endRef); //int ktagParaSegments = StTxtPara.SegmentsFlid(Cache); //int cseg = Cache.GetVectorSize(para.Hvo, ktagParaSegments); //int kflidFT = StTxtPara.SegmentFreeTranslationFlid(Cache); //ISilDataAccess sda = Cache.MainCacheAccessor; //int btWs = ViewConstructorWS; //for (int iseg = 0; iseg < cseg; iseg++) //{ // int hvoSeg = sda.get_VecItem(para.Hvo, ktagParaSegments, iseg); // if (!sda.get_IsPropInCache(hvoSeg, kflidFT, (int)CellarModuleDefns.kcptReferenceAtom, 0)) // { // StTxtPara.LoadSegmentFreeTranslations(new int[] {para.Hvo}, Cache, btWs); // } // int hvoFt = sda.get_ObjectProp(hvoSeg, kflidFT); // ITsString tssTrans = sda.get_MultiStringAlt(hvoFt, kflidComment, btWs); // int crun = tssTrans.RunCount; // for (int irun = 0; irun < crun; irun++) // { // ITsTextProps ttpRun = tssTrans.get_Properties(irun); // if (StStyle.IsStyle(ttpRun, ScrStyleNames.VerseNumber)) // { // string sVerseNum = tssTrans.get_RunText(irun); // int nVerseStart, nVerseEnd; // ScrReference.VerseToInt(sVerseNum, out nVerseStart, out nVerseEnd); // m_startRef.Verse = nVerseStart; // m_endRef.Verse = nVerseEnd; // } // else if (StStyle.IsStyle(ttpRun, ScrStyleNames.ChapterNumber)) // { // string sChapterNum = tssTrans.get_RunText(irun); // int nChapter = ScrReference.ChapterToInt(sChapterNum); // m_startRef.Chapter = m_endRef.Chapter = nChapter; // // Set the verse number to 1, since the first verse number after a // // chapter is optional. If we happen to get a verse number in the // // next run, this '1' will be overridden (though it will probably // // still be a 1). // m_startRef.Verse = m_endRef.Verse = 1; // } // } /// ------------------------------------------------------------------------------------ /// <summary> /// Inserts the IP and scrolls it to near the top of the view. Used for going to a /// location in the BT or vernacular where a verse starts (or as close as possible). /// </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="paraIndex">paragraph to look in</param> /// <param name="ichPosition">starting character index to look at</param> /// ------------------------------------------------------------------------------------ protected virtual void GoToPosition(ScrReference targetRef, int bookIndex, ScrSection section, int paraIndex, int ichPosition) { if (ContentType == StVc.ContentTypes.kctSimpleBT) { GotoVerseBT(targetRef, bookIndex, section, paraIndex, new ScrTxtPara(m_cache, section[paraIndex].Hvo)); } else if (ContentType == StVc.ContentTypes.kctSegmentBT) { GotoVerseBtSeg(targetRef, bookIndex, section, paraIndex, new ScrTxtPara(m_cache, section[paraIndex].Hvo), ichPosition); } else { SetInsertionPoint((int)ScrSection.ScrSectionTags.kflidContent, bookIndex, section.IndexInBook, paraIndex, ichPosition, false, VwScrollSelOpts.kssoNearTop); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Goes to the verse reference in the back translation paragraph or the closest /// location to where it would occur /// </summary> /// ------------------------------------------------------------------------------------ protected virtual void GotoVerseBT(ScrReference targetRef, int bookIndex, ScrSection section, int paraIndex, ScrTxtPara para) { ScrVerseSet verseSet = new ScrVerseSetBT(para, ViewConstructorWS); // Look for an exact match of the target verse number in the BT para foreach (ScrVerse verse in verseSet) { if (!verse.VerseNumberRun) continue; if (verse.StartRef <= targetRef && targetRef <= verse.EndRef) { // set the IP here now SetInsertionPoint(bookIndex, section.IndexInBook, paraIndex, verse.TextStartIndex, false); return; } } // An exact match was not found, so look for a best guess spot for it foreach (ScrVerse verse in verseSet) { if (!verse.VerseNumberRun) continue; if (verse.StartRef >= targetRef) { // set the IP here now SetInsertionPoint(bookIndex, section.IndexInBook, paraIndex, verse.VerseStartIndex, false); return; } } // A best guess spot was not found so put the selection at the end of the paragraph SetIpAtEndOfPara(bookIndex, section.IndexInBook, paraIndex, para); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Selects text in the given verse. /// </summary> /// <param name="scrRef">The Scripture reference of the verse.</param> /// <param name="text">The specific text within the verse to look for (<c>null</c> to /// select the text of the entire verse.</param> /// <remarks> /// REVIEW (TE-4218): Do we need to add a parameter to make it possible to do a case- /// insensitive match? /// </remarks> /// ------------------------------------------------------------------------------------ public void SelectVerseText(ScrReference scrRef, ITsString text) { SelectVerseText(scrRef, text, true); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Given a Scripture section, this method returns the index of the paragraph containing /// the requested verse and the position of the character immediately following the /// verse number in that paragraph. If an exact match isn't found, the closest /// approximate place is found. /// </summary> /// <param name="section">The section whose paragraphs will be searched</param> /// <param name="targetRef">The reference being sought</param> /// <param name="iPara">The index of the paragraph where the verse was found</param> /// <param name="ichPosition">The index of the character immediately following the /// verse number in that paragraph</param> /// ------------------------------------------------------------------------------------ protected void FindVerseNumber(ScrSection section, ScrReference targetRef, out int iPara, out int ichPosition) { iPara = 0; ichPosition = 0; bool fChapterFound = (BCVRef.GetChapterFromBcv(section.VerseRefMin) == targetRef.Chapter); foreach (StTxtPara para in section.ContentOA.ParagraphsOS) { TsStringAccessor contents = para.Contents; if (para.Contents.Text == null) { continue; } TsRunInfo tsi; ITsTextProps ttpRun; int ich = 0; while (ich < contents.UnderlyingTsString.Length) { // Get props of current run. ttpRun = contents.UnderlyingTsString.FetchRunInfoAt(ich, out tsi); // See if it is our verse number style. if (fChapterFound) { if (StStyle.IsStyle(ttpRun, ScrStyleNames.VerseNumber)) { // The whole run is the verse number. Extract it. string sVerseNum = contents.Text.Substring(tsi.ichMin, tsi.ichLim - tsi.ichMin); int startVerse, endVerse; ScrReference.VerseToInt(sVerseNum, out startVerse, out endVerse); if ((targetRef.Verse >= startVerse && targetRef.Verse <= endVerse) || targetRef.Verse < startVerse) { ichPosition = tsi.ichLim; return; } } } // See if it is our chapter number style. else if (StStyle.IsStyle(ttpRun, ScrStyleNames.ChapterNumber)) { try { // Assume the whole run is the chapter number. Extract it. string sChapterNum = contents.Text.Substring(tsi.ichMin, tsi.ichLim - tsi.ichMin); fChapterFound = (ScrReference.ChapterToInt(sChapterNum) == targetRef.Chapter); } catch (ArgumentException) { // ignore runs with invalid Chapter numbers } } ich = tsi.ichLim; } iPara++; } iPara = 0; // Couldn't find it. }
public void ParsePictureLoc_USFMStyleChapterRange() { int locationMin, locationMax; PictureLocationRangeType locRangeType = PictureLocationRangeType.AfterAnchor; m_scr.ParsePictureLoc("MRK 1--2", 41002003, ref locRangeType, out locationMin, out locationMax); Assert.AreEqual(new BCVRef(41, 1, 1), locationMin); ScrReference refMax = new ScrReference(41, 2, 1, m_scr.Versification); refMax.Verse = refMax.LastVerse; Assert.AreEqual(refMax, locationMax); Assert.AreEqual(PictureLocationRangeType.ReferenceRange, locRangeType); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determine if the section contains a given reference /// </summary> /// ------------------------------------------------------------------------------------ public bool ContainsReference(ScrReference reference) { return(VerseRefMin <= reference && reference <= VerseRefMax); }
/// ------------------------------------------------------------------------------------- /// <summary> /// Create all of the ScrBookRef objects for each book of Scripture /// </summary> /// <param name="progressDlg">Progress dialog so the user can cancel</param> /// ------------------------------------------------------------------------------------- protected void CreateScrBookRefs(IAdvInd4 progressDlg) { IScrRefSystem scr = m_cache.ScriptureReferenceSystem; // If there are books existing, then delete them first. for (int i = scr.BooksOS.Count - 1; i >= 0; i--) { scr.BooksOS.RemoveAt(i); } XmlDocument doc = new XmlDocument(); doc.Load(DirectoryFinder.FWCodeDirectory + @"\Translation Editor\ScrBookRef.xml"); ILgWritingSystemFactory wsf = m_cache.LanguageWritingSystemFactoryAccessor; //Select and display the value of all the ISBN attributes. XmlNodeList tagList = doc.SelectNodes("/ScrBookRef/writingsystem"); progressDlg.SetRange(0, tagList.Count * ScrReference.LastBook); progressDlg.Position = 0; progressDlg.Title = TeResourceHelper.GetResourceString("kstidCreatingBookNames"); foreach (XmlNode writingSystem in tagList) { XmlAttributeCollection attributes = writingSystem.Attributes; string sLocale = attributes.GetNamedItem("iculocale").Value; int ws = m_cache.LanguageEncodings.GetWsFromIcuLocale(sLocale); if (ws == 0) { // It is possible that the XML file contains more languages than the // database. If so, just ignore this writing system. continue; } short iBook = 0; XmlNodeList WSBooks = writingSystem.SelectNodes("book"); foreach (XmlNode book in WSBooks) { XmlAttributeCollection bookAttributes = book.Attributes; string sSilBookId = bookAttributes.GetNamedItem("SILBookId").Value; Debug.Assert(sSilBookId != null); // Make sure books are coming in canonical order. Debug.Assert(ScrReference.BookToNumber(sSilBookId) == iBook + 1); string sName = bookAttributes.GetNamedItem("Name").Value; string sAbbrev = bookAttributes.GetNamedItem("Abbreviation").Value; string sAltName = bookAttributes.GetNamedItem("AlternateName").Value; progressDlg.Message = string.Format( TeResourceHelper.GetResourceString("kstidCreatingBookNamesStatusMsg"), sName); progressDlg.Step(0); // check for the book id ScrBookRef bookRef = null; if (scr.BooksOS.Count > iBook) { bookRef = (ScrBookRef)scr.BooksOS[iBook]; Debug.Assert(bookRef != null); } else { // add this book to the list bookRef = new ScrBookRef(); scr.BooksOS.Append(bookRef); } if (sName != null) { bookRef.BookName.SetAlternative(sName, ws); } if (sAbbrev != null) { bookRef.BookAbbrev.SetAlternative(sAbbrev, ws); } if (sAltName != null) { bookRef.BookNameAlt.SetAlternative(sAltName, ws); } iBook++; } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Add an annotation to a language project that applies to a single verse reference and /// a single paragraph. /// </summary> /// <param name="testBase">in-memory test base</param> /// <param name="noteText">text to include in annotation</param> /// <param name="reference">The reference.</param> /// <param name="para">IStTxtPara to annotate</param> /// <returns>a new annotation</returns> /// ------------------------------------------------------------------------------------ internal static IScrScriptureNote AddAnnotation(ScrInMemoryFdoTestBase testBase, string noteText, ScrReference reference, ICmObject para) { return(AddAnnotation(testBase, noteText, reference, reference, para, para)); }
/// ------------------------------------------------------------------------------------ /// <summary> /// /// </summary> /// <param name="e"></param> /// ------------------------------------------------------------------------------------ protected override void OnKeyDown(KeyEventArgs e) { int buttonToGoTo = -1; switch (e.KeyCode) { case Keys.Up: buttonToGoTo = CurrentButton.ButtonAbove; break; case Keys.Left: buttonToGoTo = CurrentButton.ButtonLeft; break; case Keys.Right: buttonToGoTo = CurrentButton.ButtonRight; break; case Keys.Down: if ((e.Modifiers & Keys.Alt) > 0) { bool fCancel = (m_nowShowing == ListTypes.Books); if (fCancel) { m_scRef = ScrReference.Empty; } Close(fCancel); } else { buttonToGoTo = CurrentButton.ButtonBelow; } break; case Keys.Enter: if (m_nowShowing == ListTypes.Verses || m_fBooksOnly) { m_scRef.Verse = m_fBooksOnly ? 1 : CurrentButton.BCVValue; ScrPassageControl.ScReference = m_scRef; Close(false); return; } ButtonSelected(CurrentButton); break; case Keys.Escape: m_scRef = ScrReference.Empty; Close(); break; default: if ((e.Modifiers & Keys.Alt) != 0 && (e.Modifiers & Keys.Control) != 0) { base.OnKeyDown(e); return; } string charPressed = ((char)e.KeyValue).ToString(); for (int iButton = m_currButton < Controls.Count - 1 ? m_currButton + 1 : 0; iButton != m_currButton; iButton++) { if (m_buttons[iButton].Text.StartsWith(charPressed)) { buttonToGoTo = iButton; break; } if (iButton == Controls.Count - 1) { iButton = -1; // Keep looking from the start of the list } } break; } if (buttonToGoTo > -1) { CurrentButton.ShadeWhenMouseOver = false; m_buttons[buttonToGoTo].ShadeWhenMouseOver = false; ButtonEnter(m_buttons[buttonToGoTo], null); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Gets the reference for this footnote. /// </summary> /// <param name="owningBook">The owning book.</param> /// <param name="para">The para to search for a Scripture reference (verse or chapter). /// </param> /// <param name="startRef">The starting reference for this footnote (updated in this /// method).</param> /// <param name="endRef">The ending reference for this footnote (updated in this /// method).</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private RefResult GetReference(IScrBook owningBook, IScrTxtPara para, BCVRef startRef, BCVRef endRef) { bool foundSelf = (para != ParaContainingOrcRA); IStFootnoteRepository footnoteRepo = Cache.ServiceLocator.GetInstance <IStFootnoteRepository>(); ITsString tssContents = para.Contents; for (int i = tssContents.RunCount - 1; i >= 0; i--) { string styleName = tssContents.get_StringProperty(i, (int)FwTextPropType.ktptNamedStyle); if (foundSelf && styleName == ScrStyleNames.VerseNumber && startRef.Verse == 0) { int nVerseStart, nVerseEnd; ScrReference.VerseToInt(tssContents.get_RunText(i), out nVerseStart, out nVerseEnd); startRef.Verse = nVerseStart; endRef.Verse = nVerseEnd; } else if (foundSelf && styleName == ScrStyleNames.ChapterNumber && startRef.Chapter == 0) { try { startRef.Chapter = endRef.Chapter = ScrReference.ChapterToInt(tssContents.get_RunText(i)); } catch (ArgumentException) { // ignore runs with invalid Chapter numbers } if (startRef.Verse == 0) { startRef.Verse = endRef.Verse = 1; } } else if (styleName == null) { IScrFootnote footnote = (IScrFootnote)footnoteRepo.GetFootnoteFromObjData(tssContents.get_StringProperty(i, (int)FwTextPropType.ktptObjData)); if (footnote != null) { if (footnote == this) { foundSelf = true; continue; } RefRange otherFootnoteLocation = ((ScrFootnote)footnote).FootnoteRefInfo_Internal; if (foundSelf && otherFootnoteLocation != RefRange.EMPTY) { // Found another footnote with a reference we can use if (startRef.Verse == 0) { startRef.Verse = otherFootnoteLocation.StartRef.Verse; endRef.Verse = otherFootnoteLocation.EndRef.Verse; } if (startRef.Chapter == 0) { startRef.Chapter = otherFootnoteLocation.StartRef.Chapter; endRef.Chapter = otherFootnoteLocation.EndRef.Chapter; } } else if (foundSelf) { // Previous footnote does not have a reference yet. We presume, for performance // reasons, that none of the previous footnotes have valid references yet, so // we set all the footnotes for the book. ((ScrBook)owningBook).RefreshFootnoteRefs(); return(RefResult.ScannedAllFootnotes); } } } if (startRef.Verse != 0 && endRef.Verse != 0 && startRef.Chapter != 0 && endRef.Chapter != 0) { return(RefResult.Found); } } return(RefResult.NotFound); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Construct a DummyScrImportFileInfo. /// </summary> /// <param name="fileName">Name of the file whose info this represents</param> /// <param name="domain">The import domain to which this file belongs</param> /// <param name="icuLocale">The ICU locale of the source to which this file belongs /// (null for Scripture source)</param> /// <param name="noteTypeHvo">The HVO of the CmAnnotationDefn of the source to which /// this file belongs (only used for Note sources)</param> /// <param name="booksInFile">A list of integers representing 1-based canonical book /// numbers that are in this file</param> /// <param name="fileEncoding">The file encoding</param> /// <param name="startRef">The first reference encountered in the file</param> /// ------------------------------------------------------------------------------------ public DummyScrImportFileInfo(string fileName, ImportDomain domain, string icuLocale, int noteTypeHvo, List <int> booksInFile, Encoding fileEncoding, ScrReference startRef) : base(fileName, null, domain, icuLocale, noteTypeHvo, false) { m_booksInFile = booksInFile; m_fileEncoding = fileEncoding; m_startRef = startRef; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Adjust the start and end section references to reflect the content of the section. /// </summary> /// <param name="fIsIntro">if set to <c>true</c> this is an intro section.</param> /// ------------------------------------------------------------------------------------ public void AdjustReferences(bool fIsIntro) { // If this is not the first section then get the previous section's end reference // as a starting point for this section ScrSection prevSection = PreviousSection; ScrReference currentRefStart = new ScrReference(OwningBook.CanonicalNum, 1, 0, Cache.LangProject.TranslatedScriptureOA.Versification); if (prevSection != null) { currentRefStart.BBCCCVVV = prevSection.VerseRefEnd; } // If this is not an intro section then start the verse at 1 so it will not // be an intro section. if (currentRefStart.Verse == 0 && !fIsIntro) { currentRefStart.Verse = 1; } // Default the starting reference for the case that there is no content. int newSectionStart = currentRefStart; // Scan the paragraphs of the section to get the min and max references ScrReference refMin = new ScrReference(currentRefStart); ScrReference refMax = new ScrReference(currentRefStart); ScrReference currentRefEnd = new ScrReference(currentRefStart); bool isFirstTextRun = true; if (ContentOA != null) { foreach (StTxtPara para in ContentOA.ParagraphsOS) { ITsString paraContents = para.Contents.UnderlyingTsString; int iLim = paraContents.RunCount; RefRunType runType = RefRunType.None; for (int iRun = 0; iRun < iLim;) { // for very first run in StText we want to set VerseRefStart int iLimTmp = (iRun == 0 && isFirstTextRun) ? iRun + 1 : iLim; runType = Scripture.GetNextRef(iRun, iLimTmp, paraContents, true, ref currentRefStart, ref currentRefEnd, out iRun); // If a verse or chapter was found, adjust the max and min if the current // verse refs are less than min or greater than max if (runType != RefRunType.None) { // If a chapter or verse is found at the start of the section, then use that // reference instead of the one from the previous section as the min and max. if (isFirstTextRun || currentRefStart < refMin) { refMin.BBCCCVVV = currentRefStart.BBCCCVVV; } if (isFirstTextRun || currentRefEnd > refMax) { refMax.BBCCCVVV = currentRefEnd.BBCCCVVV; } } // after the first run, store the starting reference if (isFirstTextRun) { newSectionStart = currentRefStart; isFirstTextRun = false; } } } } // Store the min and max as the reference range for the section VerseRefStart = newSectionStart; VerseRefMin = refMin; VerseRefMax = refMax; // Store the last reference for the section. bool verseRefEndHasChanged = (VerseRefEnd != currentRefEnd.BBCCCVVV); bool verseRefEndChapterHasChanged = (BCVRef.GetChapterFromBcv(VerseRefEnd) != currentRefEnd.Chapter); VerseRefEnd = currentRefEnd; // If the last reference changes then the next section's references have potentially been invalidated ScrSection nextSection = NextSection; if (nextSection != null) { if ((verseRefEndChapterHasChanged && !nextSection.StartsWithChapterNumber) || (verseRefEndHasChanged && !nextSection.StartsWithVerseOrChapterNumber)) { nextSection.AdjustReferences(); } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determines next chapter following current reference /// </summary> /// <returns></returns> /// ------------------------------------------------------------------------------------ public ScrReference GetNextChapter() { CheckDisposed(); ScrReference curEndRef = CurrentEndRef; if (curEndRef.Book == 0) { // REVIEW BobA(TimS): Something went wrong, let's move to the first verse // we know of... Alternative is to say oh well, and do nothing at all. return ScrReference.StartOfBible(curEndRef.Versification); } if (curEndRef.Chapter == 0) { // Hmmm... we're probably at the beginning of the book already, and in the // title or intro area. We should move into the previous book. if (BookIndex >= 0) { // We are in the intro section area, we should move to the // first verse of the first chapter ScrBook book = BookFilter.GetBook(BookIndex); return new ScrReference((short)book.CanonicalNum, 1, 1, m_scr.Versification); } } else { // Standard yum-cha situation here... move up to the next chapter // and be happy. if (BookIndex >= 0 && SectionIndex >= 0) { ScrBook book = BookFilter.GetBook(BookIndex); int lastChapter = 0; foreach (ScrSection section in book.SectionsOS) { ScrReference maxSectionRef = new ScrReference(section.VerseRefMax, m_scr.Versification); ScrReference minSectionRef = new ScrReference(section.VerseRefMin, m_scr.Versification); if (minSectionRef.Valid && maxSectionRef.Valid && maxSectionRef.Chapter > lastChapter) { lastChapter = maxSectionRef.Chapter; } } if (BookIndex == BookFilter.BookCount - 1 && curEndRef.Chapter == lastChapter) { // We're at the end of the book, nowhere to go... return new ScrReference((short)book.CanonicalNum, lastChapter, 1, m_scr.Versification); } if (curEndRef.Chapter == lastChapter) { // We're at the end of the book, nowhere to go... book = BookFilter.GetBook(BookIndex + 1); return new ScrReference((short)book.CanonicalNum, 1, 1, m_scr.Versification); } // Otherwise, move on.... we were bored of this part anyhow... return new ScrReference((short)book.CanonicalNum, curEndRef.Chapter + 1, 1, m_scr.Versification); } } // Splode? return ScrReference.StartOfBible(curEndRef.Versification); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Attempts to find the specified text in the given verse and return the character /// offsets (relative to the whole paragraph) to allow it to be selected. /// </summary> /// <param name="scr">The scripture.</param> /// <param name="tssTextToFind">The text to search for</param> /// <param name="scrRef">The reference of the verse in which to look</param> /// <param name="fMatchWholeWord">True to match to a whole word, false to just look /// for the specified text</param> /// <param name="iSection">Index of the section where the text was found.</param> /// <param name="iPara">Index of the para in the section contents.</param> /// <param name="ichStart">if found, the character offset from the start of the para to /// the start of the sought text</param> /// <param name="ichEnd">if found, the character offset from the start of the para to /// the end of the sought text</param> /// <returns> /// <c>true</c> if found; <c>false</c> otherwise /// </returns> /// ------------------------------------------------------------------------------------ public static bool FindTextInVerse(IScripture scr, ITsString tssTextToFind, ScrReference scrRef, bool fMatchWholeWord, out int iSection, out int iPara, out int ichStart, out int ichEnd) { // Get verse text int verseStart; List<VerseTextSubstring> verseTextList = GetVerseText(scr, scrRef, out verseStart); foreach (VerseTextSubstring verseText in verseTextList) { // Search for word form in verse text if (StringUtils.FindTextInString(tssTextToFind, verseText.Tss, scr.Cache.LanguageWritingSystemFactoryAccessor, fMatchWholeWord, out ichStart, out ichEnd)) { ichStart += verseStart; ichEnd += verseStart; iSection = verseText.SectionIndex; iPara = verseText.ParagraphIndex; return true; } verseStart = 0; } ichStart = ichEnd = iSection = iPara = -1; return false; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Finds all ORCs in the given text and notes any orphaned footnotes or pictures. /// </summary> /// <param name="text">The text.</param> /// <param name="textLocationInfo">Additional information about the location of the /// text that can help the user find it.</param> /// <param name="startRef">Caller should pass in the initial reference to use as the /// basis for any references found in the course of parsing the text. Returned value /// will be the final reference found, which can be used as the basis for the subsequent /// text</param> /// <param name="endRef">Same as startRef, except in the case of verse bridges or /// section headings</param> /// <param name="footnotes">List of footnotes owned by the book that owns the /// given text. As footnotes are found, their locations will be set.</param> /// <param name="parasWithOrcs">List of paragraphs and ORC positions.</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private static bool FindOrcsWithoutPropsInText(IStText text, string textLocationInfo, ref BCVRef startRef, ref BCVRef endRef, List <FootnoteOrcLocation> footnotes, List <OrcLocation> parasWithOrcs) { bool foundOrphan = false; foreach (IStTxtPara para in text.ParagraphsOS) { ITsString tssContents = para.Contents.UnderlyingTsString; string sContents = tssContents.Text; if (sContents == null) { continue; } int nRun = tssContents.RunCount; for (int i = 0; i < nRun; i++) { TsRunInfo runInfo; ITsTextProps tprops = tssContents.FetchRunInfo(i, out runInfo); string styleName = tprops.GetStrPropValue( (int)FwTextPropType.ktptNamedStyle); // When a verse number is encountered, save the number into // the reference. if (styleName == ScrStyleNames.VerseNumber) { string sVerseNum = sContents.Substring(runInfo.ichMin, runInfo.ichLim - runInfo.ichMin); int nVerseStart, nVerseEnd; ScrReference.VerseToInt(sVerseNum, out nVerseStart, out nVerseEnd); startRef.Verse = nVerseStart; endRef.Verse = nVerseEnd; } // If a chapter number is encountered then save the number into // the reference and start the verse number back at 1. else if (styleName == ScrStyleNames.ChapterNumber) { try { string sChapterNum = sContents.Substring(runInfo.ichMin, runInfo.ichLim - runInfo.ichMin); startRef.Chapter = endRef.Chapter = ScrReference.ChapterToInt(sChapterNum); startRef.Verse = endRef.Verse = 1; } catch (ArgumentException) { // ignore runs with invalid Chapter numbers } } else { // search contents for ORCs for (int ich = runInfo.ichMin; ich < runInfo.ichLim; ich++) { if (sContents[ich] != StringUtils.kchObject) { continue; } OrcLocation orcLocation = new OrcLocation(para, ich, startRef, endRef, textLocationInfo); parasWithOrcs.Add(orcLocation); ITsTextProps props = tssContents.get_PropertiesAt(ich); string objData = props.GetStrPropValue((int)FwTextPropType.ktptObjData); if (objData == null) { foundOrphan = true; } else { // first char. of strData is type code - GUID will follow it. Guid objGuid = MiscUtils.GetGuidFromObjData(objData.Substring(1)); int hvo = text.Cache.GetIdFromGuid(objGuid); int classId = (hvo == 0) ? 0 : text.Cache.GetClassOfObject(hvo); if (classId == StFootnote.kClassId) { foreach (FootnoteOrcLocation footnote in footnotes) { if (footnote.footnote.Hvo == hvo) { orcLocation.Object = footnote.footnote; footnote.location = orcLocation; break; } } } else if (classId == 0) { foundOrphan = true; } else { Debug.Assert(classId == CmPicture.kClassId, "Unknown class id in embedded object: " + classId); orcLocation.Object = classId; } } } } } } return(foundOrphan); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Initialize the scripture importer /// </summary> /// ------------------------------------------------------------------------------------ protected void Initialize() { m_wsAnal = m_cache.DefaultAnalWs; m_wsVern = m_cache.DefaultVernWs; m_wsPara = m_cache.DefaultVernWs; m_scr = m_cache.LangProject.TranslatedScriptureOA; InitInterpretFootnoteSettings(); ScrImportSet importSettings = (m_settings as ScrImportSet); // ENHANCE (TomB): Might want to make it possible to end importing in the middle // of a book someday. ScrReference endRef = new ScrReference(importSettings.EndRef, m_scr.Versification); ScrReference startRef = new ScrReference(importSettings.StartRef, m_scr.Versification); m_nBookNumber = importSettings.StartRef.Book; importSettings.EndRef = endRef = endRef.LastReferenceForBook; // Initialize scripture object InitScriptureObject(); // Load the scripture text project & enum LoadScriptureProject(); // Display progress if one was supplied if (m_importCallbacks.IsDisplayingUi) { int cChapters = ScrReference.GetNumberOfChaptersInRange(SOWrapper.BooksPresent, startRef, endRef); int nMax = m_settings.ImportTranslation ? cChapters : 0; if (SOWrapper.HasNonInterleavedBT && m_settings.ImportBackTranslation) nMax += cChapters; if (SOWrapper.HasNonInterleavedNotes && m_settings.ImportAnnotations) nMax += cChapters; m_importCallbacks.Maximum = nMax; } // Init our set of style proxies LoadImportMappingProxies(); // Init member vars special paragraph style proxies, used as fallbacks in case // import data lacks a paragraph style. // For now we always use the default vernacular writing system. This may change // when we are able to import paratext project proxies with multiple // domains (vern, back transl, notes) m_BookTitleParaProxy = new ImportStyleProxy(ScrStyleNames.MainBookTitle, StyleType.kstParagraph, m_wsVern, ContextValues.Title, m_styleSheet); Debug.Assert(m_BookTitleParaProxy.Context == ContextValues.Title); m_ScrSectionHeadParaProxy = new ImportStyleProxy(ScrStyleNames.SectionHead, StyleType.kstParagraph, m_wsVern, ContextValues.Text, m_styleSheet); m_DefaultIntroSectionHeadParaProxy = new ImportStyleProxy(ScrStyleNames.IntroSectionHead, StyleType.kstParagraph, m_wsVern, ContextValues.Intro, m_styleSheet); m_DefaultScrParaProxy = new ImportStyleProxy(ScrStyleNames.NormalParagraph, StyleType.kstParagraph, m_wsVern, ContextValues.Text, m_styleSheet); m_DefaultIntroParaProxy = new ImportStyleProxy(ScrStyleNames.IntroParagraph, StyleType.kstParagraph, m_wsVern, ContextValues.Intro, m_styleSheet); m_DefaultFootnoteParaProxy = new ImportStyleProxy(ScrStyleNames.NormalFootnoteParagraph, StyleType.kstParagraph, m_wsVern, ContextValues.Note, m_styleSheet); m_DefaultAnnotationStyleProxy = new ImportStyleProxy(ScrStyleNames.Remark, StyleType.kstParagraph, m_wsAnal, ContextValues.Annotation, m_styleSheet); // Make a paragraph builder. We will keep re-using this every time we build a paragraph. m_ParaBldr = new StTxtParaBldr(m_cache); // Handle the case where the very first marker (after the \id line) is a // character style. m_ParaBldr.ParaStylePropsProxy = m_DefaultIntroParaProxy; // Build generic character props for use with different runs of text and analysis // character properties ITsPropsBldr tsPropsBldr = TsPropsBldrClass.Create(); // analysis character properties tsPropsBldr.SetIntPropValues((int)FwTextPropType.ktptWs, 0, m_wsAnal); m_analTextProps = tsPropsBldr.GetTextProps(); // vernacular character properties tsPropsBldr.SetIntPropValues((int)FwTextPropType.ktptWs, 0, m_wsVern); m_vernTextProps = tsPropsBldr.GetTextProps(); // Get a reference to the annotation definition of translator notes (to use as default note type) m_scrTranslatorAnnotationDef = new CmAnnotationDefn(m_cache, LangProject.kguidAnnTranslatorNote); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Generates a cannonical text form of the given reference, consisting of /// book abbreviation (in primary writing system), chapter nbr, colon, verse nbr. /// </summary> /// <param name="scRef">The given scReference object.</param> /// <returns>The generated text string reference.</returns> /// ------------------------------------------------------------------------------------ public virtual string GetRefString(ScrReference scRef) { return(scRef.AsString); // GetAbbrev, replace 1st 3 with new abbrev }
/// ------------------------------------------------------------------------------------ /// <summary> /// Loop through the runs of the given string until a verse or chapter number is /// found. Update the start and end reference with the found number. /// </summary> /// <param name="iStart">Index of run to start search</param> /// <param name="iLim">Index of run to end search. /// One exception: if the run at iLim-1 is a chapter, we will go one run further (at the /// iLim) to check for an adjacent verse number.</param> /// <param name="tss">The string</param> /// <param name="fIgnoreErrors"><c>true</c> to ignore runs with errors, <c>false</c> /// to throw an exception if we encounter a invalid chapter or verse number.</param> /// <param name="refStart">Start reference</param> /// <param name="refEnd">End reference</param> /// <param name="iNext">Index of run after last one processed (i.e. iCurr+1)</param> /// <exception cref="T:System.ArgumentException">Invalid chapter number</exception> /// ------------------------------------------------------------------------------------ public static RefRunType GetNextRef(int iStart, int iLim, ITsString tss, bool fIgnoreErrors, ref ScrReference refStart, ref ScrReference refEnd, out int iNext) { Debug.Assert(iStart >= 0 && iStart < iLim); Debug.Assert(iLim <= tss.RunCount); // look at all of the text runs in this paragraph starting at int iRun = iStart; try { for (; iRun < iLim; iRun++) { TsRunInfo runInfo; string style = tss.FetchRunInfo(iRun, out runInfo).Style(); if (style == ScrStyleNames.VerseNumber) { // for verse number runs, get the verse range and save it int startVerse, endVerse; ScrReference.VerseToInt(tss.get_RunText(iRun), out startVerse, out endVerse); if (startVerse <= 0) { if (fIgnoreErrors) continue; throw new InvalidVerseException(tss.get_RunText(iRun), runInfo); } if (startVerse <= refStart.LastVerse) { refStart.Verse = startVerse; refEnd.Verse = Math.Min(refEnd.LastVerse, endVerse); } iNext = iRun + 1; return RefRunType.Verse; } if (style == ScrStyleNames.ChapterNumber) { int chapter = -1; try { // for chapter number runs, get the chapter number and save it chapter = ScrReference.ChapterToInt(tss.get_RunText(iRun)); } catch (ArgumentException) { if (fIgnoreErrors) continue; throw new InvalidChapterException(tss.get_RunText(iRun), runInfo); } Debug.Assert(chapter > 0); // should have thrown exception in ScrReference.ChapterToInt // if chapter is valid for this book... if (chapter <= refStart.LastChapter) { refStart.Chapter = refEnd.Chapter = chapter; refStart.Verse = refEnd.Verse = 1; // implicit default } iNext = iRun + 1; // increment just beyond the chapter // Because we've found a chapter, check the very next run (if we can) // to see if it is a verse. if (iNext < tss.RunCount && iNext < iLim + 1) // it's ok to check at iLim in this special case { int dummy; ScrReference startTemp = new ScrReference(refStart); ScrReference endTemp = new ScrReference(refEnd); RefRunType nextItemType = GetNextRef(iNext, iNext + 1, tss, fIgnoreErrors, ref startTemp, ref endTemp, out dummy); // if it is a verse, update refStart/refEnd if (nextItemType == RefRunType.Verse) { refStart = startTemp; refEnd = endTemp; iNext++; return RefRunType.ChapterAndVerse; } } // Otherwise, since a verse didn't immediatly follow, verse 1 is implicit // so use it as the refStart/RefEnd return RefRunType.Chapter; } } iNext = iLim; return RefRunType.None; } catch { // Set iNext in case caller handles the exception. We don't want to deal // with same run again. iNext = iRun + 1; throw; } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Read the file to build mappings of the markers found /// </summary> /// ------------------------------------------------------------------------------------ protected void GetMappingsFromStream(TextReader reader) { string lineIn; int chapter = -1; int book = -1; int lineCount = 0; // book and chapter strings for reporting info in exceptions string sBookId = null; string sChapter = null; string sVerse = null; // Keep track of the first reference in the file int firstBook = -1; int firstChapter = -1; int firstVerse = -1; ReferenceRange currentRange = null; string marker; string lineText; string nextLineText = null; // used for read-ahead for \fig line when doing strict scanning while ((lineIn = reader.ReadLine()) != null) { lineCount++; while (GetNextMarkerFromData(lineIn, out marker, out lineText)) { // Make sure the marker is valid if (!IsValidMarker(marker)) { throw new ScriptureUtilsException(SUE_ErrorCode.InvalidCharacterInMarker, m_fileName, lineCount, lineIn, sBookId, sChapter, sVerse); } ImportMappingInfo markerMapping = GetOrCreateMarkerMapping(ref marker); if (marker == ScrImportSet.s_markerBook) { sBookId = lineText.TrimStart().ToUpperInvariant(); // save the book number in the list for this file book = ScrReference.BookToNumber(sBookId); if (book <= 0) { throw new ScriptureUtilsException(SUE_ErrorCode.InvalidBookID, m_fileName, lineCount, lineIn, sBookId, null, null); } sBookId = ScrReference.NumberToBookCode(book); // Make a new reference range with the book id and // start it out with chapter range of 0-0. AddRangeToList(currentRange); currentRange = new ReferenceRange(book, 0, 0); // If this is the first book, remember it if (firstBook == -1) { firstBook = book; } m_booksInFile.Add(book); chapter = -1; } else { // make sure that a book has been started before seeing any non-excluded markers // This error is a "strict" error because files can be added by a user before there // is a chance to exclude markers in the mappings. When the file is added from the settings // for import, then strict checking will be on. if (book == -1 && m_doStrictFileChecking) { // if the marker is not excluded then throw an error if (markerMapping != null && !markerMapping.IsExcluded) { throw new ScriptureUtilsException(SUE_ErrorCode.UnexcludedDataBeforeIdLine, m_fileName, lineCount, lineIn, null, null, null); } } if (marker == ScrImportSet.s_markerChapter) { // If there is no book, then throw an error since chapter numbers // are not valid without a book if (book == -1) { throw new ScriptureUtilsException(SUE_ErrorCode.ChapterWithNoBook, m_fileName, lineCount, lineIn, null, null, null); } try { sChapter = lineText; chapter = ScrReference.ChapterToInt(sChapter); // save the chapter number as the last chapter and possibly the first // chapter number in the range. if (currentRange.StartChapter == 0) { currentRange.StartChapter = chapter; } currentRange.EndChapter = chapter; } catch (ArgumentException) { throw new ScriptureUtilsException(SUE_ErrorCode.InvalidChapterNumber, m_fileName, lineCount, lineIn, sBookId, sChapter, null); } // If this is the first chapter, remember it if (firstChapter == -1) { firstChapter = chapter; } } else if (marker == ScrImportSet.s_markerVerse) { // If a verse is seen without a book, throw an exception if (book == -1) { throw new ScriptureUtilsException(SUE_ErrorCode.VerseWithNoBook, m_fileName, lineCount, lineIn, sBookId, null, lineText); } BCVRef firstRef = new BCVRef(book, chapter, 0); BCVRef lastRef = new BCVRef(book, chapter, 0); // check for an invalid verse number if (!BCVRef.VerseToScrRef(lineText, ref firstRef, ref lastRef) || firstRef.Verse == 0 || firstRef.Verse > lastRef.Verse) { throw new ScriptureUtilsException(SUE_ErrorCode.InvalidVerseNumber, m_fileName, lineCount, lineIn, sBookId, sChapter, lineText); } // If a chapter number has not been seen yet, then throw an exception sVerse = firstRef.Verse.ToString(); if (chapter == -1 && !SingleChapterBook(book)) { throw new ScriptureUtilsException(SUE_ErrorCode.MissingChapterNumber, m_fileName, lineCount, lineIn, sBookId, null, sVerse); } // If this is the first verse, remember it if (firstVerse == -1) { firstVerse = firstRef.Verse; } } else if (!markerMapping.IsExcluded && m_doStrictFileChecking && markerMapping.MappingTarget == MappingTargetType.Figure) { // First, we need to consider whether any following lines also need // to be read in, since the Figure parameters could be split across // lines. (TE-7669) Debug.Assert(nextLineText == null); int cExtraLinesRead = 0; string sTempMarker, sTempLineText; if (!GetNextMarkerFromData(lineText, out sTempMarker, out sTempLineText)) { while ((nextLineText = reader.ReadLine()) != null) { cExtraLinesRead++; if (GetNextMarkerFromData(nextLineText, out sTempMarker, out sTempLineText)) { // Normally, we want to break the line right before the first marker. int ichMarkerPos = nextLineText.IndexOf(sTempMarker); // But if it's a \fig*, break after the marker. if (sTempMarker == markerMapping.EndMarker) { ichMarkerPos += sTempMarker.Length; } lineText += " " + nextLineText.Substring(0, ichMarkerPos); nextLineText = nextLineText.Substring(ichMarkerPos); break; } else { lineText += " " + nextLineText; } } } string figureParams = lineText; int endMarkerLength = 0; // Validate the tokens for a mapping target (only in strict checking) if (!String.IsNullOrEmpty(markerMapping.EndMarker)) { endMarkerLength = markerMapping.EndMarker.Length; int ichEnd = figureParams.IndexOf(markerMapping.EndMarker); if (ichEnd >= 0) { figureParams = figureParams.Substring(0, ichEnd); } else { endMarkerLength = 0; // end marker is optional and not present } } string[] tokens = figureParams.Split(new char[] { '|' }); if (tokens.Length < 6) { throw new ScriptureUtilsException(SUE_ErrorCode.BadFigure, m_fileName, lineCount, lineIn, sBookId, sChapter, sVerse); } lineText = lineText.Substring(figureParams.Length + endMarkerLength); lineCount += cExtraLinesRead; } } // Mark this mapping as "in-use" because it was found in the scanned file markerMapping.SetIsInUse(m_domain, m_icuLocale, m_noteTypeHvo, true); if (m_scanInlineBackslashMarkers) { lineIn = lineText; } else { lineIn = nextLineText; nextLineText = null; if (lineIn == null) { break; } } if (string.IsNullOrEmpty(lineIn) && !string.IsNullOrEmpty(nextLineText)) { lineIn = nextLineText; nextLineText = null; } } } // Add the last range to the list AddRangeToList(currentRange); // If no books were found in the file then throw an exception if (book == -1) { throw new ScriptureUtilsException(SUE_ErrorCode.MissingBook, m_fileName, lineCount, null, null, null, null); } // If no chapters were found then throw an exception if (chapter == -1 && !SingleChapterBook(book)) { throw new ScriptureUtilsException(SUE_ErrorCode.NoChapterNumber, m_fileName, lineCount, null, sBookId, null, null); } // Store the first reference for the file m_startRef.Book = firstBook; m_startRef.Chapter = firstChapter == -1 ? 1 : firstChapter; m_startRef.Verse = firstVerse == -1 ? 1 : firstVerse; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Look for the given picture's ORC in the given verse. /// </summary> /// <param name="targetRef">The verse reference to look for</param> /// <param name="hvoPict">The hvo of the picture to look for.</param> /// <param name="iSection">The index of the section where the ORC was found.</param> /// <param name="iPara">The index of the para where the ORC was found.</param> /// <param name="ichOrcPos">The character position of the ORC in the paragraph.</param> /// <returns> /// <c>true</c> if the given picture is found in the given verse. /// </returns> /// ------------------------------------------------------------------------------------ public bool FindPictureInVerse(ScrReference targetRef, int hvoPict, out int iSection, out int iPara, out int ichOrcPos) { CheckDisposed(); iSection = iPara = ichOrcPos = -1; // Find the book that the reference is in IScrBook book = ScrBook.FindBookByID(m_scr, targetRef.Book); if (book == null) return false; iSection = 0; // Look through the sections for the target reference foreach (ScrSection section in book.SectionsOS) { if (section.ContainsReference(targetRef)) { iPara = 0; // Look through each paragraph in the section foreach (StTxtPara para in section.ContentOA.ParagraphsOS) { // Search for target reference in the verses in the paragraph ScrTxtPara scrPara = new ScrTxtPara(m_cache, para.Hvo); ScrVerseSet verseSet = new ScrVerseSet(scrPara); foreach (ScrVerse verse in verseSet) { if (verse.StartRef <= targetRef && targetRef <= verse.EndRef) { // If the paragraph has a chapter number, the verse iterator // returns this as a separate string with the same reference // as the following verse. // We want to return the verse string, not the chapter number // run, so we skip a string that has only numeric characters. ITsString tssVerse = verse.Text; for (int iRun = 0; iRun < tssVerse.RunCount; iRun++) { string sRun = tssVerse.get_RunText(iRun); if (sRun.Length == 1 && sRun[0] == StringUtils.kchObject) { string str = tssVerse.get_Properties(iRun).GetStrPropValue( (int)FwTextPropType.ktptObjData); if (!String.IsNullOrEmpty(str) && str[0] == (char)(int)FwObjDataTypes.kodtGuidMoveableObjDisp) { Guid guid = MiscUtils.GetGuidFromObjData(str.Substring(1)); if (m_cache.GetIdFromGuid(guid) == hvoPict) { ichOrcPos = tssVerse.get_MinOfRun(iRun) + verse.VerseStartIndex; return true; } } } } } } iPara++; } } iSection++; } return false; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Convert the reference range to a string /// </summary> /// <returns></returns> /// ------------------------------------------------------------------------------------ public override string ToString() { return(ScrReference.NumberToBookCode(Book) + " " + StartChapter + "-" + EndChapter); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Selects text in the given verse. /// </summary> /// <param name="scrRef">The Scripture reference of the verse.</param> /// <param name="text">The specific text within the verse to look for (<c>null</c> to /// select the text of the entire verse.</param> /// <param name="fSynchScroll">if set to <c>true</c> then use the flavor of GotoVerse /// that will send a synch. message. Otherwise, the other flavor is used.</param> /// <remarks> /// REVIEW (TE-4218): Do we need to add a parameter to make it possible to do a case- /// insensitive match? /// </remarks> /// ------------------------------------------------------------------------------------ public void SelectVerseText(ScrReference scrRef, ITsString text, bool fSynchScroll) { if (scrRef.Versification != m_scr.Versification) scrRef = new ScrReference(scrRef, m_scr.Versification); if (!(fSynchScroll ? GotoVerse(scrRef) : GotoVerse_WithoutSynchMsg(scrRef))) return; bool fOrigIgnoreAnySyncMessages = false; if (m_syncHandler != null) { fOrigIgnoreAnySyncMessages = m_syncHandler.IgnoreAnySyncMessages; m_syncHandler.IgnoreAnySyncMessages = !fSynchScroll; } try { // We successfully navigated to the verse (or somewhere close) so attempt to make a // selection there. int ichStart, ichEnd; if (text == null || text.Text == null) { int verseStart; List<VerseTextSubstring> verseTexts = GetVerseText(m_scr, scrRef, out verseStart); if (verseTexts.Count == 0) return; // Must not have found the exact verse SelectionHelper helper = CurrentSelection; helper.IchEnd = (verseTexts.Count == 1) ? verseStart + verseTexts[0].Length : verseTexts[verseTexts.Count - 1].Length; if (verseTexts[verseTexts.Count - 1].SectionIndex != verseTexts[0].SectionIndex) { SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.End); int iParaLev = LocationTrackerImpl.GetLevelIndexForTag((int)StText.StTextTags.kflidParagraphs, StVc.ContentTypes.kctNormal); int iSectLev = LocationTrackerImpl.GetLevelIndexForTag((int)ScrBook.ScrBookTags.kflidSections, StVc.ContentTypes.kctNormal); levInfo[iParaLev].ihvo = verseTexts[verseTexts.Count - 1].ParagraphIndex; levInfo[iSectLev].ihvo += (verseTexts[verseTexts.Count - 1].SectionIndex - verseTexts[0].SectionIndex); helper.SetLevelInfo(SelectionHelper.SelLimitType.End, levInfo); } else if (verseTexts.Count > 1) { SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.End); int iParaLev = LocationTrackerImpl.GetLevelIndexForTag((int)StText.StTextTags.kflidParagraphs, StVc.ContentTypes.kctNormal); levInfo[iParaLev].ihvo = verseTexts[verseTexts.Count - 1].ParagraphIndex; helper.SetLevelInfo(SelectionHelper.SelLimitType.End, levInfo); } helper.SetSelection(true); } else { int iSection, iPara; if (FindTextInVerse(m_scr, text, scrRef, false, out iSection, out iPara, out ichStart, out ichEnd)) { // We found the text in the verse. if (!InBookTitle) SelectRangeOfChars(BookIndex, iSection, iPara, ichStart, ichEnd); else { SelectRangeOfChars(BookIndex, iSection, (int)ScrBook.ScrBookTags.kflidTitle, iPara, ichStart, ichEnd, true, true, false); } } } } finally { if (m_syncHandler != null) m_syncHandler.IgnoreAnySyncMessages = fOrigIgnoreAnySyncMessages; } }
private ScrReference InternalImport(IScrImportSet importSettings, bool fDisplayUi) { ScrReference firstImported = ScrReference.Empty; bool fPartialBtImported = false; try { Logger.WriteEvent("Starting import"); using (var progressDlg = new ProgressDialogWithTask(m_mainWnd, m_cache.ThreadHelper)) { progressDlg.CancelButtonText = TeResourceHelper.GetResourceString("kstidStopImporting"); progressDlg.Title = TeResourceHelper.GetResourceString("kstidImportProgressCaption"); progressDlg.Message = TeResourceHelper.GetResourceString("kstidImportInitializing"); if (importSettings == null) // XML (OXES) import { progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; } using (TeImportUi importUi = CreateTeImportUi(progressDlg)) { firstImported = (ScrReference)progressDlg.RunTask(fDisplayUi, ImportTask, importSettings, m_undoImportManager, importUi); } } } catch (WorkerThreadException e) { if (e.InnerException is ScriptureUtilsException) { var se = (ScriptureUtilsException)e.InnerException; if (m_helpTopicProvider != null) { string sCaption = GetDialogCaption(se.ImportErrorCodeType); // TODO-Linux: Help is not implemented in Mono MessageBox.Show(m_mainWnd, se.Message, sCaption, MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0, m_helpTopicProvider.HelpFile, HelpNavigator.Topic, se.HelpTopic); } if (se.ImportErrorCodeType == ErrorCodeType.BackTransErrorCode && !se.InterleavedImport) { fPartialBtImported = true; } } else if (e.InnerException is ParatextLoadException) { if (!MiscUtils.RunningTests) { Logger.WriteError(e); string sCaption = ScriptureUtilsException.GetResourceString("kstidImportErrorCaption"); Exception innerE = e.InnerException; var sbMsg = new StringBuilder(innerE.Message); while (innerE.InnerException != null) { innerE = innerE.InnerException; sbMsg.AppendLine(); sbMsg.Append(innerE.Message); } MessageBoxUtils.Show(m_mainWnd, sbMsg.ToString(), sCaption, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else if (!(e.InnerException is CancelException)) { // User didn't just cancel import in the middle of a book -- let's die. throw; } } if (m_undoImportManager.ImportedBooks.Count == 0 && !fPartialBtImported) { Logger.WriteEvent("Nothing imported. Undoing Import."); // Either there was nothing in the file, or the user canceled during the first book. // In any case, we didn't get any books, so whatever has been done should be undone. m_undoImportManager.UndoEntireImport(); return(null); } return(firstImported); }
/// <summary> /// Go to the indicated verse in the BT. We've already determined the index of the book, the section, /// the paragraph, and the character index in the vernacular. We want to figure the corresponding /// position in the BT, which should be the non-label segment closest to (hopefully containing) the /// vernacular position, and select it. /// </summary> /// <param name="targetRef"></param> /// <param name="bookIndex"></param> /// <param name="section"></param> /// <param name="paraIndex"></param> /// <param name="para"></param> /// <param name="ichMainPosition">The position where this verse occurs in the main paragraph.</param> protected virtual void GotoVerseBtSeg(ScrReference targetRef, int bookIndex, ScrSection section, int paraIndex, ScrTxtPara para, int ichMainPosition) { int isegTarget = GetBtSegIndexForVernChar(para, ichMainPosition, ViewConstructorWS); // Select the appropriate segment (or if nothing matched, the last place we can edit). if (isegTarget < 0) return; // pathological. SelectRangeOfChars(bookIndex, section.IndexInBook, (int)ScrSection.ScrSectionTags.kflidContent, paraIndex, isegTarget, 0, 0, true, true, false, VwScrollSelOpts.kssoDefault); }
public bool GotoVerse(ScrReference targetRef) { throw new NotImplementedException(); }
///// ------------------------------------------------------------------------------------ ///// <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> /// Advances the enumerator to the next element of the collection. /// </summary> /// <returns> /// true if the enumerator was successfully advanced to the next element; false if the /// enumerator has passed the end of the collection. /// </returns> /// <exception cref="T:System.InvalidOperationException">The collection was modified /// after the enumerator was created. </exception> /// ------------------------------------------------------------------------------------ public bool MoveNext() { if (m_currentScrText == null) { return(false); } while (++m_currentScrText.m_iRun < m_currentScrText.m_paraTss.RunCount) { m_internalToken.m_fParagraphStart = (m_currentScrText.m_iRun == 0); ITsTextProps runProps = m_currentScrText.m_paraTss.get_Properties(m_currentScrText.m_iRun); string charStyleName = runProps.GetStrPropValue((int)FwTextPropType.ktptNamedStyle); m_internalToken.m_sText = m_currentScrText.m_paraTss.get_RunText(m_currentScrText.m_iRun); m_internalToken.m_paraOffset = m_currentScrText.m_paraTss.get_MinOfRun(m_currentScrText.m_iRun); int var; int ws = runProps.GetIntPropValues((int)FwTextPropType.ktptWs, out var); m_internalToken.m_icuLocale = GetLocale(ws); m_internalToken.Ws = ws; switch (runProps.GetStrPropValue((int)FwTextPropType.ktptNamedStyle)) { case ScrStyleNames.VerseNumber: if (!m_foundStart || string.IsNullOrEmpty(m_internalToken.m_sText)) { continue; } m_internalToken.m_textType = TextType.VerseNumber; int verse = ScrReference.VerseToIntStart(m_internalToken.m_sText); if (verse != 0) { m_internalToken.m_startRef.Verse = verse; } verse = ScrReference.VerseToIntEnd(m_internalToken.m_sText); if (verse != 0) { m_internalToken.m_endRef.Verse = verse; } break; case ScrStyleNames.ChapterNumber: if (string.IsNullOrEmpty(m_internalToken.m_sText)) { continue; } int chapter = 0; try { chapter = ScrReference.ChapterToInt(m_internalToken.m_sText); } catch { // Ignore exceptions. We'll flag them later as errors. } if (!m_foundStart) { if (m_chapterNum != chapter) { continue; } m_foundStart = true; } else if (m_chapterNum > 0 && m_chapterNum != chapter) { // Stop if we're only getting tokens for a single chapter (unless // this is an (erroneous) second occurrence of the same chapter) return(false); } m_internalToken.m_textType = TextType.ChapterNumber; m_internalToken.m_startRef.Chapter = m_internalToken.m_endRef.Chapter = chapter; m_internalToken.m_startRef.Verse = m_internalToken.m_endRef.Verse = 1; break; default: { if (!m_foundStart) { continue; } // Deal with footnotes and picture captions Guid guidObj = TsStringUtils.GetGuidFromRun(m_currentScrText.m_paraTss, m_currentScrText.m_iRun, runProps); if (guidObj == Guid.Empty) { m_internalToken.m_textType = m_currentScrText.DefaultTextType; } else if (m_outerText != null) { // It was possible through copy/paste to put ORCs into footnotes or pictures, but that is no // longer allowed. This tokenizing code won't handle the nesting correctly, so just ignore // the nested ORC. See TE-8609. continue; } else { m_fOrcWasStartOfPara = m_internalToken.m_fParagraphStart; ICmObject obj; m_book.Cache.ServiceLocator.GetInstance <ICmObjectRepository>().TryGetObject(guidObj, out obj); if (obj is IStFootnote) { m_outerText = m_currentScrText; // footnotes are StTexts m_currentScrText = new TokenizableText((IStText)obj, TextType.Note); return(MoveNext()); } if (obj is ICmPicture) { m_outerText = m_currentScrText; ICmPicture pict = (ICmPicture)obj; m_currentScrText = new TokenizableText( pict.Caption.VernacularDefaultWritingSystem, ScrStyleNames.Figure, TextType.PictureCaption, pict, CmPictureTags.kflidCaption); return(MoveNext()); } } } break; } m_internalToken.m_fNoteStart = (m_internalToken.m_textType == TextType.Note && m_internalToken.m_fParagraphStart && m_currentScrText.m_iPara == 0); m_internalToken.m_paraStyleName = m_currentScrText.ParaStyleName; m_internalToken.m_charStyleName = charStyleName != null ? charStyleName : string.Empty; m_internalToken.m_object = m_currentScrText.m_obj; m_internalToken.m_flid = m_currentScrText.m_flid; // We need the current token to be a copy of our internal token so we don't change the // internal variables of whatever was returned from the enumerator. m_currentToken = m_internalToken.Copy(); return(true); } // Finished that paragraph and didn't find any more runs; try next para in this text, // if any. if (!m_currentScrText.NextParagraph()) { if (!m_foundStart) { Debug.Fail("We should have found the desired chapter wtihin the section we were searching."); return(false); } // Finished that text and didn't find any more paragraphs. // If we have been processing an inner text (footnote or picture caption), pop back // out to the "outer" one. if (m_outerText != null) { m_currentScrText = m_outerText; m_outerText = null; bool result = MoveNext(); if (result) { m_currentToken.m_fParagraphStart |= m_fOrcWasStartOfPara; m_fOrcWasStartOfPara = false; } return(result); } // Otherwise, try next text, if any. if (m_currentScrText.m_text.OwningFlid == ScrBookTags.kflidTitle) { // Get first section head text. CurrentSectionIndex = 0; } else if (m_currentScrText.m_text.OwningFlid == ScrSectionTags.kflidHeading) { m_currentScrText = new TokenizableText(m_currentSection.ContentOA, m_currentSection.IsIntro ? TextType.Other : TextType.Verse); } else { Debug.Assert(m_currentScrText.m_text.OwningFlid == ScrSectionTags.kflidContent); if (m_iCurrentSection + 1 >= m_book.SectionsOS.Count) { return(false); } CurrentSectionIndex++; if (m_chapterNum > 0 && ScrReference.GetChapterFromBcv(m_currentSection.VerseRefStart) != m_chapterNum) { return(false); } } } return(MoveNext()); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determine chapter before current reference. /// </summary> /// <returns></returns> /// ------------------------------------------------------------------------------------ public ScrReference GetPrevChapter() { CheckDisposed(); ScrReference curStartRef = CurrentStartRef; if (curStartRef.Book == 0) return ScrReference.Empty; if (curStartRef.Chapter == 0) { // Hmmm... we're probably at the beginning of the book already, and in the // title or intro area. We should move into the previous book. if (BookIndex > 0) { ScrBook book = BookFilter.GetBook(BookIndex - 1); int chapter = 0; foreach (ScrSection section in book.SectionsOS) { ScrReference minRef = new ScrReference(section.VerseRefMin, m_scr.Versification); ScrReference maxRef = new ScrReference(section.VerseRefMax, m_scr.Versification); if (minRef.Valid && maxRef.Valid) { for (int i = BCVRef.GetChapterFromBcv(section.VerseRefMin); i <= BCVRef.GetChapterFromBcv(section.VerseRefMax); i++) { if (i > chapter) chapter = i; } } } return new ScrReference((short)book.CanonicalNum, chapter, 1, m_scr.Versification); } if (BookIndex == 0) { // Guess what, we're at the beginning, just move to the first // chapter/verse in the book. ScrBook book = BookFilter.GetBook(0); return new ScrReference((short)book.CanonicalNum, 1, 1, m_scr.Versification); } } else { // Standard yum-cha situation here... move up to the previous chapter // and be happy. if (BookIndex >= 0 && SectionIndex >= 0) { ScrBook book = BookFilter.GetBook(BookIndex); if (curStartRef.Chapter > 1) { return new ScrReference((short)book.CanonicalNum, curStartRef.Chapter - 1, 1, m_scr.Versification); } if (BookIndex > 0) { // We are at the first chapter of the book so move to the last chapter in // the previous book. book = BookFilter.GetBook(BookIndex - 1); int chapter = 0; if (book.SectionsOS.Count > 0) chapter = BCVRef.GetChapterFromBcv(book.LastSection.VerseRefMax); return new ScrReference((short)book.CanonicalNum, chapter, 1, m_scr.Versification); } return new ScrReference((short)book.CanonicalNum, 1, 1, m_scr.Versification); } } // Splode? return ScrReference.Empty; }
public void CompareScrRefBooks() { ScrReference gen = new ScrReference(1, 1, 1, ScrVers.English); ScrReference exo = new ScrReference(2, 1, 1, ScrVers.English); Assert.Less(m_comparer.Compare(gen, exo), 0); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Goes to the text referenced in the ScrScriptureNote. If it does not find the text, /// it makes the closest selection to the referenced text that it can. /// </summary> /// <param name="note">the note containing the Scripture reference to find</param> /// <param name="sendSyncMsg"><c>true</c> to not send a focus sychronization message /// when the selection is changed by going to the scripture ref.</param> /// ------------------------------------------------------------------------------------ public void GoToScrScriptureNoteRef(IScrScriptureNote note, bool sendSyncMsg) { // TODO (TE-1729): Use this method correctly from Annotations view. ScrReference scrRef = new ScrReference(note.BeginRef, m_scr.Versification); ScrBook book = BookFilter.GetBookByOrd(scrRef.Book); if (book == null) return; int iBook = BookFilter.GetBookIndex(book.Hvo); bool fOrigIgnoreAnySyncMessages = false; if (m_syncHandler != null) { fOrigIgnoreAnySyncMessages = m_syncHandler.IgnoreAnySyncMessages; m_syncHandler.IgnoreAnySyncMessages = true; } try { if (note.Flid == (int)CmPicture.CmPictureTags.kflidCaption) { SelectCitedTextInPictureCaption(iBook, note); return; } int ichStart, ichEnd; string citedText = note.CitedText; ITsString citedTextTss = note.CitedTextTss; StTxtPara para = note.BeginObjectRA as StTxtPara; if (para != null && m_cache.GetOwnerOfObjectOfClass(para.Hvo, ScrDraft.kClassId) == 0) { if (para.Owner is StFootnote) { // Make selection in footnote. if (TextAtExpectedLoc(para.Contents.Text, citedText, note.BeginOffset, note.EndOffset)) { // Select text in footnote. StFootnote footnote = para.Owner as StFootnote; if (footnote == null) return; SelectionHelper selHelper = new SelectionHelper(); selHelper.AssocPrev = false; selHelper.NumberOfLevels = 3; selHelper.LevelInfo[2].tag = BookFilter.Tag; selHelper.LevelInfo[2].ihvo = iBook; selHelper.LevelInfo[1].tag = (int)ScrBook.ScrBookTags.kflidFootnotes; selHelper.LevelInfo[1].ihvo = footnote.IndexInOwner; selHelper.LevelInfo[0].ihvo = 0; // Prepare to move the IP to the specified character in the paragraph. selHelper.IchAnchor = note.BeginOffset; selHelper.IchEnd = note.EndOffset; // Now that all the preparation to set the IP is done, set it. selHelper.SetSelection(Callbacks.EditedRootBox.Site, true, true); } return; } // Make selection in Scripture text if (TextAtExpectedLoc(para.Contents.Text, citedText, note.BeginOffset, note.EndOffset)) { SelectRangeOfChars(iBook, para, note.BeginOffset, note.EndOffset); return; } if (scrRef.Verse == 0) { // Either a missing chapter number or something in intro material. // Not much chance of finding it by reference (even if the chapter number // has been added, we never find the 0th verse, and 99% of the time that // chapter number would have been added to the same paragraph where it // was missing in the first place), so just try to find the text in the // paragraph, if it still exists. if (string.IsNullOrEmpty(citedText)) { SelectRangeOfChars(iBook, para, note.BeginOffset, note.BeginOffset); return; } // The text may be null if the paragraph only contains the prompt. TE-8315 if (para.Contents.Text != null) { int i = para.Contents.Text.IndexOf(citedText); if (i >= 0) { SelectRangeOfChars(iBook, para, i, i + citedText.Length); return; } } } } // A selection could not be made at the specified location. Attempt to go to // the specified verse and then try to find the text. // REVIEW (TimS): Why do we call GotoVerse here when we select the characters // down below? We might consider doing this only if we fail down below. if (sendSyncMsg) GotoVerse(scrRef); else GotoVerse_WithoutSynchMsg(scrRef); int iSection, iPara; if (citedText != null && FindTextInVerse(m_scr, citedTextTss, scrRef, false, out iSection, out iPara, out ichStart, out ichEnd)) { // We found the text in the verse at a different character offset. SelectRangeOfChars(iBook, iSection, iPara, ichStart, ichEnd); } else if (note.BeginOffset > 0 && para != null && IsOffsetValidLoc(para.Contents.Text, note.BeginOffset)) { // We couldn't find the cited text at the specified offset, nor anywhere // in the paragraph. Therefore, just set the IP at the begin offset. SelectRangeOfChars(iBook, para, note.BeginOffset, note.BeginOffset); } } finally { if (m_syncHandler != null) m_syncHandler.IgnoreAnySyncMessages = fOrigIgnoreAnySyncMessages; } }
public void BookTitles() { ScrReference genesis = new ScrReference(1, 0, 0, ScrVers.English); ScrReference exodus = new ScrReference(2, 0, 0, ScrVers.English); Assert.AreEqual(m_comparer.Compare(genesis, 1000000), 0); Assert.Greater(m_comparer.Compare(exodus, genesis), 0); Assert.Less(m_comparer.Compare(exodus, 2001001), 0); }
public void CompareScrRefVerses() { ScrReference gen1_10 = new ScrReference(1, 1, 10, ScrVers.English); ScrReference gen1_2 = new ScrReference(1, 1, 2, ScrVers.English); Assert.Greater(m_comparer.Compare(gen1_10, gen1_2), 0); Assert.Less(m_comparer.Compare(gen1_2, gen1_10), 0); Assert.AreEqual(m_comparer.Compare(gen1_10, new ScrReference(01001010, ScrVers.English)), 0); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Initializes the form's controls from the settings in the filter. /// </summary> /// ------------------------------------------------------------------------------------ private void InitializeFromFilter() { if (m_filter == null || m_filter.RowsOS.Count == 0 || m_filter.RowsOS[0].CellsOS.Count == 0) { return; } // Get the pairs of class ids and flids. string[] pairs = m_filter.ColumnInfo.Split('|'); Debug.Assert(m_filter.RowsOS[0].CellsOS.Count == pairs.Length); for (int i = 0; i < pairs.Length; i++) { ICmCell cell = m_filter.RowsOS[0].CellsOS[i]; // Get the flid for this cell. string[] pair = pairs[i].Split(','); int flid = 0; int.TryParse(pair[1], out flid); switch (flid) { case ScrScriptureNoteTags.kflidResolutionStatus: chkStatus.Checked = true; cell.ParseIntegerMatchCriteria(); rbResolved.Checked = (cell.MatchValue == 1); rbUnresolved.Checked = (cell.MatchValue == 0); break; case CmAnnotationTags.kflidAnnotationType: chkType.Checked = true; cell.ParseObjectMatchCriteria(); Guid guid = TsStringUtils.GetGuidFromRun(cell.Contents, 1); rbConsultant.Checked = (guid == CmAnnotationDefnTags.kguidAnnConsultantNote); rbTranslator.Checked = (guid == CmAnnotationDefnTags.kguidAnnTranslatorNote); break; case CmBaseAnnotationTags.kflidBeginRef: chkScrRange.Checked = true; cell.ParseIntegerMatchCriteria(); ScrReference scrRef = new ScrReference(cell.MatchValue, m_scr.Versification); // If the reference was adjusted to 0:0 to include notes in the title and // introduction, adjust it back to 1:1 so we don't confuse the user. if (scrRef.Chapter == 0) { scrRef.Chapter = 1; } if (scrRef.Verse == 0) { scrRef.Verse = 1; } if (cell.ComparisonType == ComparisonTypes.kGreaterThanEqual) { scrBookFrom.ScReference = scrRef; } else { scrBookTo.ScReference = scrRef; } break; } } }
public void MixedReferences() { ScrReference genesis = new ScrReference(1, 1, 1, ScrVers.English); Assert.Less(m_comparer.Compare("GEN 1:1", 02001001), 0); Assert.Greater(m_comparer.Compare("EXO 1:1", genesis), 0); Assert.AreEqual(m_comparer.Compare(01001001, genesis), 0); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Handle TE specific requirements on selection change. /// </summary> /// <param name="prootb"></param> /// <param name="vwselNew"></param> /// ------------------------------------------------------------------------------------ public override void SelectionChanged(IVwRootBox prootb, IVwSelection vwselNew) { CheckDisposed(); // selection change is being done by this routine, don't need to do processing // second time. if (m_selectionUpdateInProcess) return; // Make sure we don't try to use the old selection (TE-5009). m_viewSelection = null; SelectionHelper helper = SelectionHelper.Create(vwselNew, prootb.Site); UpdateGotoPassageControl(); // update the verse reference to the new selection SetInformationBarForSelection(); // update title bar with section reference range if (MainTransVc != null) ProcessBTSelChange(helper); bool updatedSelection = false; int hvoSelObj = 0; if (helper != null && helper.LevelInfo.Length > 0) hvoSelObj = helper.LevelInfo[0].hvo; IGetTeStVc getVc = prootb.Site as IGetTeStVc; TeStVc vc = null; if (getVc != null) vc = getVc.Vc; if (vc != null && vc.SuppressCommentPromptHvo != hvoSelObj) { vc.SuppressCommentPromptHvo = 0; // Enhance JohnT: do a Propchanged (possibly delayed until idle) on hvo.Comment to make the prompt reappear. } // If the selection is in a user prompt then extend the selection to cover the // entire prompt. if (IsSelectionInPrompt(helper)) { if (vc != null) vc.SuppressCommentPromptHvo = hvoSelObj; // If we're not really showing the prompt, but just an incomplete composition that was typed // over it, we do NOT want to select all of it all the time! (TE-8267). if (!prootb.IsCompositionInProgress) vwselNew.ExtendToStringBoundaries(); if (!vwselNew.IsEditable && helper != null) { // We somehow got an IP that associates with the non-editable spacer next to the prompt. // We need to extend in the opposite direction. helper.AssocPrev = !helper.AssocPrev; IVwSelection sel = helper.SetSelection(EditedRootBox.Site, false, false); // Make sure that the new selection is editable before we install it. This keeps us // from getting here again and again (recursively). (TE-8763) if (sel.IsEditable) sel.Install(); return; // We have already been called again as the new selection is installed. } SetKeyboardForSelection(vwselNew); } // This isn't ideal but it's one of the better of several bad options for dealing // with simplifying the selection changes in footnote views. if ((m_viewType & TeViewType.FootnoteView) != 0 || (m_viewType & TeViewType.NotesDataEntryView) != 0 || helper == null) { // This makes sure the writing system and styles combos get updated. base.SelectionChanged(prootb, vwselNew); return; } // If selection is IP, don't allow it to be associated with a verse number run. bool fRangeSelection = vwselNew.IsRange; if (!fRangeSelection) PreventIPAssociationWithVerseRun(vwselNew, prootb, ref updatedSelection); // Need to do this at end since selection may be changed by this method. // Doing this at top can also cause value of style in StylesComboBox to flash base.SelectionChanged(prootb, vwselNew); // If we changed the selection in this method we want to set the viewSelection to // null so that the next time it is gotten it will have the correct selection. if (updatedSelection) m_viewSelection = null; // Make sure the selection is in a valid Scripture element. int tagSelection; int hvoSelection; if (!vwselNew.IsValid || !GetSelectedScrElement(out tagSelection, out hvoSelection)) { m_sPrevSelectedText = null; return; } // Determine whether or not the selection changed but is in a different reference. bool fInSameRef = (m_oldReference == CurrentStartRef); if (fInSameRef && !fRangeSelection) { m_sPrevSelectedText = null; if (m_syncHandler != null) m_syncHandler.SyncToScrLocation(this, this, true); return; } ScrReference curStartRef = CurrentStartRef; if (curStartRef.Chapter == 0) curStartRef.Chapter = 1; m_oldReference = CurrentStartRef; string selectedText = null; if (fRangeSelection) { try { ITsString tssSelectedText = GetCleanSelectedText(); selectedText = (tssSelectedText != null ? tssSelectedText.Text : null); } catch { selectedText = null; } } bool fSameSelectedText = (m_sPrevSelectedText == selectedText); m_sPrevSelectedText = selectedText; if (m_syncHandler != null && (!fInSameRef || !fSameSelectedText || InBookTitle || InSectionHead || InIntroSection)) { m_syncHandler.SyncToScrLocation(this, this, fInSameRef); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Test CheckForOverlaps where the user elects to keep file 1 in the Overlapping Files /// dialog /// </summary> /// ------------------------------------------------------------------------------------ private IScrImportFileInfo CreateStubFileInfo(DummyScrImportFileInfoFactory factory, string name, ScrReference startRef, ReferenceRange refRange) { IScrImportFileInfo f = factory.Create(name, m_mappingList, ImportDomain.Main, null, null, false); f.Stub(x => x.IsReadable).Return(true); f.Stub(x => x.IsStillReadable).Return(true); f.Stub(x => x.StartRef).Return(startRef); f.Stub(x => x.BookReferences).Return(new ReferenceRange[] { refRange }); return f; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Attempt to set the selection immediately following the desired verse reference. /// This version of GotoVerse sends a synch message at the end, so it should not be /// called from within code that is already responding to a synch message. /// </summary> /// <param name="targetRef">Reference to seek</param> /// <returns>true if the selection is changed (to the requested verse or one nearby); /// false otherwise</returns> /// <remarks> /// Searching will start at the current selection location and wrap around if necessary. /// If the verse reference is not included in the range of any sections, then the /// selection will not be changed. If the reference does not exist but it is in the /// range of a section, then a best guess will be done. /// </remarks> /// ------------------------------------------------------------------------------------ public virtual bool GotoVerse(ScrReference targetRef) { bool retVal = GotoVerse_WithoutSynchMsg(targetRef); if (m_syncHandler != null) m_syncHandler.SyncToScrLocation(this, this, false); return retVal; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Finalizes section references and checks if the current section has any heading text /// and content. If not, a single blank paragraph is written for whatever is missing. /// </summary> /// ------------------------------------------------------------------------------------ protected void FinalizePrevSection() { if (m_currSection == null || !m_currSection.IsValidObject()) return; m_currSection.AdjustReferences(!m_fInScriptureText); int bcvRef = (m_firstImportedRef.IsEmpty) ? m_currSection.VerseRefMin : Math.Min(m_firstImportedRef, m_currSection.VerseRefMin); m_firstImportedRef = new ScrReference(bcvRef, m_scr.Versification); if (InMainImportDomain) return; // First, check if there is heading content. If not, add a blank paragraph. if (m_currSection.HeadingOA.ParagraphsOS.Count == 0) { StTxtParaBldr paraBldr = new StTxtParaBldr(m_cache); paraBldr.ParaStylePropsProxy = (m_fInScriptureText ? m_ScrSectionHeadParaProxy : m_DefaultIntroSectionHeadParaProxy); paraBldr.StringBuilder.SetIntPropValues(0, 0, (int)FwTextPropType.ktptWs, (int)FwTextPropVar.ktpvDefault, m_wsVern); paraBldr.CreateParagraph(m_hvoSectionHeading); } // Now, check if there is content. If not, add a blank paragraph. if (m_currSection.ContentOA.ParagraphsOS.Count == 0) { StTxtParaBldr paraBldr = new StTxtParaBldr(m_cache); paraBldr.ParaStylePropsProxy = (m_fInScriptureText ? m_DefaultScrParaProxy : m_DefaultIntroParaProxy); paraBldr.StringBuilder.SetIntPropValues(0, 0, (int)FwTextPropType.ktptWs, (int)FwTextPropVar.ktpvDefault, m_wsVern); paraBldr.CreateParagraph(m_hvoSectionContent); } m_fInScriptureText = !m_fCurrentSectionIsIntro; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Attempt to set the selection immediately following the desired verse reference. /// This version of GotoVerse does not issue a synch message, so it is suitable for /// calling from the /// </summary> /// <param name="targetRef">Reference to seek</param> /// <returns>true if the selection is changed (to the requested verse or one nearby); /// false otherwise</returns> /// <remarks> /// Searching will start at the current selection location and wrap around if necessary. /// If the verse reference is not included in the range of any sections, then the /// selection will not be changed. If the reference does not exist but it is in the /// range of a section, then a best guess will be done. /// </remarks> /// ------------------------------------------------------------------------------------ private bool GotoVerse_WithoutSynchMsg(ScrReference targetRef) { CheckDisposed(); bool origIgnoreAnySyncMessages = false; if (m_syncHandler != null) { origIgnoreAnySyncMessages = m_syncHandler.IgnoreAnySyncMessages; m_syncHandler.IgnoreAnySyncMessages = true; } try { ScrBook bookToLookFor = BookFilter.GetBookByOrd(targetRef.Book); if (bookToLookFor == null) return false; int iBook = BookFilter.GetBookIndex(bookToLookFor.Hvo); if (targetRef.IsBookTitle) { SelectRangeOfChars(iBook, -1, (int)ScrBook.ScrBookTags.kflidTitle, 0, 0, 0, true, true, false, VwScrollSelOpts.kssoNearTop); return true; } // If the book has no sections, then don't look for any references Debug.Assert(bookToLookFor.SectionsOS.Count > 0); if (bookToLookFor.SectionsOS.Count == 0) return false; int startingSectionIndex = 0; int startingParaIndex = 0; int startingCharIndex = 0; // Get the current selection if (CurrentSelection != null) { ILocationTracker tracker = ((ITeView)Control).LocationTracker; // If the selection is in the desired book, we start there. // Otherwise start at the beginning of the book if (tracker.GetBookHvo(CurrentSelection, SelectionHelper.SelLimitType.Anchor) == bookToLookFor.Hvo) { int tmpSectionIndex = tracker.GetSectionIndexInBook( CurrentSelection, SelectionHelper.SelLimitType.Anchor); if (tmpSectionIndex >= 0) { startingSectionIndex = tmpSectionIndex; SelLevInfo paraInfo; if (CurrentSelection.GetLevelInfoForTag( (int)StText.StTextTags.kflidParagraphs, out paraInfo)) { startingParaIndex = paraInfo.ihvo; // Start looking 1 character beyond the current selection. startingCharIndex = CurrentSelection.IchEnd + 1; } } } } ScrSection startingSection = bookToLookFor[startingSectionIndex]; ScrSection section; int paraIndex; int ichVerseStart; // Decide which section to start with. If the current selection // is at the end of the section then start with the next section StTxtPara lastParaOfSection = startingSection.LastContentParagraph; if (startingParaIndex >= startingSection.ContentParagraphCount - 1 && startingCharIndex >= lastParaOfSection.Contents.Length) { startingSection = (startingSection.NextSection ?? bookToLookFor.FirstSection); startingParaIndex = 0; startingCharIndex = 0; } if (bookToLookFor.GetRefStartFromSection(targetRef, false, startingSection, startingParaIndex, startingCharIndex, out section, out paraIndex, out ichVerseStart)) { // We found an exact match, so go there. GoToPosition(targetRef, iBook, section, paraIndex, ichVerseStart); } else { // We didn't find an exact match, so go somewhere close. GotoClosestPrecedingRef(targetRef, bookToLookFor); } return true; } finally { if (m_syncHandler != null) m_syncHandler.IgnoreAnySyncMessages = origIgnoreAnySyncMessages; } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Looks for any annotations in the curtrently filtered set whose reference range /// covers the given Scripture reference. Any such annotations are expanded and the /// first on is scrolled to near the top of the view. /// </summary> /// ------------------------------------------------------------------------------------ internal void ScrollRefIntoView(ScrReference reference, string quotedText) { CheckDisposed(); if (reference.Book <= 0) return; bool fSaveSendSyncScrollMsg = m_fSendSyncScrollMsg; try { m_fSendSyncScrollMsg = false; int bookHvo = m_scr.BookAnnotationsOS[reference.Book - 1].Hvo; int[] annHvos = ((ISilDataAccessManaged)m_rootb.DataAccess).VecProp(bookHvo, kCurrentNotesTag); int exactMatchingAnnotation = -1; int firstMatchingAnnotation = -1; for (int i = 0; i < annHvos.Length; i++) { IScrScriptureNote ann = Cache.ServiceLocator.GetInstance<IScrScriptureNoteRepository>().GetObject(annHvos[i]); if (ann.BeginRef <= reference && ann.EndRef >= reference) { if (firstMatchingAnnotation < 0) firstMatchingAnnotation = i; string qtext = ((IStTxtPara)ann.QuoteOA[0]).Contents.Text; if (!string.IsNullOrEmpty(qtext) && !string.IsNullOrEmpty(quotedText) && qtext == quotedText && exactMatchingAnnotation < 0) { exactMatchingAnnotation = i; } } else if (firstMatchingAnnotation >= 0) break; } int idx = Math.Max(exactMatchingAnnotation, firstMatchingAnnotation); if (idx >= 0) NotesEditingHelper.MakeSelectionInNote(m_vc, reference.Book - 1, idx, this, m_vc.IsExpanded(annHvos[idx])); } finally { m_fSendSyncScrollMsg = fSaveSendSyncScrollMsg; } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Find a verse and return the text of the verse in one or more /// <see cref="VerseTextSubstring"/> objects. /// </summary> /// <param name="scr">The scripture.</param> /// <param name="targetRef">The verse reference to look for</param> /// <param name="ichStart">The starting character where the (first part of the) verse /// text is located within the (first) containing paragraph</param> /// <returns> /// A list of <see cref="VerseTextSubstring"/> objects, each representing /// one paragraph worth of verse text (e.g., to deal with poetry) /// </returns> /// <remarks>Verses would not normally be split across sections, but there are a few /// places, such as the end of I Cor. 12, where it can happen. /// </remarks> /// ------------------------------------------------------------------------------------ public static List<VerseTextSubstring> GetVerseText(IScripture scr, ScrReference targetRef, out int ichStart) { ichStart = -1; if (scr.Versification != targetRef.Versification) targetRef = new ScrReference(targetRef, scr.Versification); List<VerseTextSubstring> verseText = new List<VerseTextSubstring>(); // Find the book that the reference is in IScrBook book = ScrBook.FindBookByID(scr, targetRef.Book); if (book == null) return verseText; if (targetRef.IsBookTitle) { foreach (StTxtPara para in book.TitleOA.ParagraphsOS) { verseText.Add(new VerseTextSubstring(para.Contents.UnderlyingTsString, -1, para.IndexInOwner, (int)ScrBook.ScrBookTags.kflidTitle)); ichStart = 0; } return verseText; } int iSection = 0; // Look through the sections for the target reference foreach (ScrSection section in book.SectionsOS) { if (!section.ContainsReference(targetRef)) { if (verseText.Count > 0) return verseText; } else { int iPara = 0; // Look through each paragraph in the section foreach (StTxtPara para in section.ContentOA.ParagraphsOS) { // Search for target reference in the verses in the paragraph ScrTxtPara scrPara = new ScrTxtPara(scr.Cache, para.Hvo); ScrVerseSet verseSet = new ScrVerseSet(scrPara); foreach (ScrVerse verse in verseSet) { if (verse.StartRef <= targetRef && targetRef <= verse.EndRef) { // If the paragraph has a chapter number, the verse iterator // returns this as a separate string with the same reference // as the following verse. // We want to return the verse string, not the chapter number // run, so we skip a string that has only numeric characters. ITsString verseTextInPara = verse.Text; if (verse.Text.RunCount > 0) { string styleName = verse.Text.get_PropertiesAt(0).GetStrPropValue( (int)FwTextPropType.ktptNamedStyle); if (styleName == ScrStyleNames.VerseNumber) verseTextInPara = StringUtils.Substring(verseTextInPara, verse.Text.get_LimOfRun(0)); } if (!IsNumber(verseTextInPara.Text)) // skip chapter number strings { if (verseText.Count == 0) ichStart = verse.TextStartIndex; verseText.Add(new VerseTextSubstring(verseTextInPara, iSection, iPara, (int)ScrSection.ScrSectionTags.kflidContent)); break; } } else if (verseText.Count > 0) return verseText; } iPara++; } } iSection++; } return verseText; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the chapter verse bridge for a given section, formatted appropriately for the UI /// writing system /// </summary> /// ------------------------------------------------------------------------------------ public string ChapterVerseBridgeAsString(IScrSection section) { if (section.IsIntro) { return String.Format(Strings.ksScriptureSectionIntroduction, section.OwnOrd); } ScrReference startRef = new ScrReference(section.VerseRefStart, Versification); ScrReference endRef = new ScrReference(section.VerseRefEnd, Versification); if (startRef.Chapter != endRef.Chapter) { return MakeBridgeAsString(ChapterVerseRefAsString(startRef, m_cache.DefaultUserWs), ChapterVerseRefAsString(endRef, m_cache.DefaultUserWs), m_cache.DefaultUserWs); } return ChapterVerseBridgeAsString(startRef, endRef, m_cache.DefaultUserWs); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Looks for any annotations in the curtrently filtered set whose reference range /// covers the given Scripture reference. Any such annotations are expanded and the /// first on is scrolled to near the top of the view. /// </summary> /// ------------------------------------------------------------------------------------ internal void ScrollRelevantAnnotationIntoView(TeEditingHelper editingHelper) { CheckDisposed(); Debug.Assert(editingHelper != null); if (editingHelper.BookIndex < 0) { return; } bool fSaveSendSyncScrollMsg = m_fSendSyncScrollMsg; try { m_fSendSyncScrollMsg = false; ScrReference scrRef = editingHelper.CurrentStartRef; if (!scrRef.Valid) { return; // No valid reference to scroll to } ITsString tss = editingHelper.GetCleanSelectedText(); string selectedText = (tss != null ? tss.Text : null); // If there's no range selection in scripture and the IP is in the // same reference as that of the current annotation, then don't scroll // to a different annotation, even if there is another one for the // same reference. if (selectedText == null && CurrentAnnotation != null && scrRef == CurrentAnnotation.BeginRef) { return; } selectedText = (selectedText ?? editingHelper.CleanSelectedWord); // Try to find the exact annotation associated with the selection. if (ScrollToAnnotationByPara(editingHelper, selectedText, CurrentAnnotation != null && scrRef == CurrentAnnotation.BeginRef)) { return; } // When the passed editing helper's selection is in a book title, section heading // or intro. material, then find the annotation for that selection's paragraph. if (editingHelper.InBookTitle || editingHelper.InSectionHead || editingHelper.InIntroSection) { if (ScrollToNonScrAnnotationByBook(scrRef.Book, selectedText)) { return; } } if (CurrentAnnotation == null || scrRef != CurrentAnnotation.BeginRef) { ScrollRefIntoView(scrRef, selectedText); } } finally { m_fSendSyncScrollMsg = fSaveSendSyncScrollMsg; } }