protected virtual IList <CharacterVerse> ProcessLine(string[] items, int lineNumber) { var list = new List <CharacterVerse>(); if (items.Length < kiQuoteType) { throw new ApplicationException("Bad format in CharacterVerse control file! Line #: " + lineNumber + "; Line contents: " + string.Join("\t", items)); } if (items.Length > kMaxItems) { throw new ApplicationException("Incorrect number of fields in CharacterVerse control file! Line #: " + lineNumber + "; Line contents: " + string.Join("\t", items)); } int chapter; if (!Int32.TryParse(items[1], out chapter)) { Debug.Assert(false, string.Format("Invalid chapter number ({0}) on line {1}: {2}", items[1], lineNumber, items[0])); } for (int verse = ScrReference.VerseToIntStart(items[2]); verse <= ScrReference.VerseToIntEnd(items[2]); verse++) { list.Add(CreateCharacterVerse(new BCVRef(BCVRef.BookToNumber(items[0]), chapter, verse), items)); } return(list); }
/// <summary> /// Add the working block to the new list and create a new working block /// </summary> /// <param name="styleTag"></param> /// <param name="nonNarrator"></param> private void FlushBlock(string styleTag, bool nonNarrator) { if (!m_workingBlock.BlockElements.Any()) { m_workingBlock.StyleTag = styleTag; return; } if (nonNarrator) { if (m_nextBlockContinuesQuote) { m_workingBlock.MultiBlockQuote = MultiBlockQuote.Continuation; } m_nextBlockContinuesQuote = m_quoteLevel > 0; if (m_nextBlockContinuesQuote && m_workingBlock.MultiBlockQuote != MultiBlockQuote.Continuation) { m_workingBlock.MultiBlockQuote = MultiBlockQuote.Start; } m_workingBlock.SetCharacterAndDelivery( m_cvInfo.GetCharacters(m_bookNum, m_workingBlock.ChapterNumber, m_workingBlock.InitialStartVerseNumber, m_workingBlock.InitialEndVerseNumber, m_workingBlock.LastVerse, m_versification)); } else { m_nextBlockContinuesQuote = false; m_workingBlock.SetStandardCharacter(m_bookId, CharacterVerseData.StandardCharacter.Narrator); } switch (m_workingBlock.MultiBlockQuote) { case MultiBlockQuote.Start: ProcessMultiBlock(); m_currentMultiBlockQuote.Add(m_workingBlock); break; case MultiBlockQuote.Continuation: m_currentMultiBlockQuote.Add(m_workingBlock); break; case MultiBlockQuote.None: ProcessMultiBlock(); break; } m_outputBlocks.Add(m_workingBlock); var lastVerse = m_workingBlock.BlockElements.OfType <Verse>().LastOrDefault(); int verseStartNum = m_workingBlock.InitialStartVerseNumber; int verseEndNum = m_workingBlock.InitialEndVerseNumber; if (lastVerse != null) { verseStartNum = ScrReference.VerseToIntStart(lastVerse.Number); verseEndNum = ScrReference.VerseToIntEnd(lastVerse.Number); } m_workingBlock = new Block(styleTag, m_workingBlock.ChapterNumber, verseStartNum, verseEndNum); }
public IEnumerable <Block> Parse() { var titleBuilder = new StringBuilder(); IList <Block> blocks = new List <Block>(); foreach (XmlNode node in m_nodeList) { Block block = null; switch (node.Name) { case "chapter": AddMainTitleIfApplicable(blocks, titleBuilder); m_chapterNodeFound = true; block = ProcessChapterNode(node); if (block == null) { continue; } break; case "para": if (!node.HasChildNodes) { continue; } var usxPara = new UsxNode(node); IStyle style = m_stylesheet.GetStyle(usxPara.StyleTag); if (style.IsChapterLabel) { block = ProcessChapterLabelNode(node.InnerText, usxPara); if (block == null) { continue; } // The node before this was the chapter. We already added it, then found this label. // Remove that block so it will be replaced with this one. blocks.RemoveAt(blocks.Count - 1); break; } if (style.IsParallelPassageReference || !style.IsPublishable) { continue; } if (style.HoldsBookNameOrAbbreviation) { if (style.Id.StartsWith("mt")) { titleBuilder.Append(node.InnerText).Append(" "); if (style.Id == "mt1") { MainTitle = node.InnerText; } } else if (style.Id == "h") { PageHeader = node.InnerText; } continue; } AddMainTitleIfApplicable(blocks, titleBuilder); block = new Block(usxPara.StyleTag, m_currentChapter, m_currentStartVerse, m_currentEndVerse) { IsParagraphStart = true }; if (m_currentChapter == 0) { block.SetStandardCharacter(m_bookId, CharacterVerseData.StandardCharacter.Intro); } else if (style.IsPublishable && !style.IsVerseText) { block.SetStandardCharacter(m_bookId, CharacterVerseData.StandardCharacter.ExtraBiblical); } var sb = new StringBuilder(); // <verse number="1" style="v" /> // Acakki me lok me kwena maber i kom Yecu Kricito, Wod pa LubaĆa, // <verse number="2" style="v" /> // <note caller="-" style="x"><char style="xo" closed="false">1.2: </char><char style="xt" closed="false">Mal 3.1</char></note> // kit ma gicoyo kwede i buk pa lanebi Icaya ni,</para> foreach (XmlNode childNode in usxPara.ChildNodes) { switch (childNode.Name) { case "verse": if (sb.Length > 0) { sb.TrimStart(); block.BlockElements.Add(new ScriptText(sb.ToString())); sb.Clear(); } RemoveLastElementIfVerse(block); var verseNumStr = childNode.Attributes.GetNamedItem("number").Value; m_currentStartVerse = ScrReference.VerseToIntStart(verseNumStr); m_currentEndVerse = ScrReference.VerseToIntEnd(verseNumStr); if (!block.BlockElements.Any() || (block.BlockElements.Count == 1 && block.FirstTextElementIsOnlyPunctuation)) { block.InitialStartVerseNumber = m_currentStartVerse; block.InitialEndVerseNumber = m_currentEndVerse; } block.BlockElements.Add(new Verse(verseNumStr)); break; case "char": IStyle charStyle = m_stylesheet.GetStyle((new UsxNode(childNode)).StyleTag); if (!charStyle.IsInlineQuotationReference && charStyle.IsPublishable) { sb.Append(childNode.InnerText); } break; case "#text": sb.Append(childNode.InnerText); break; case "#whitespace": if (sb.Length > 0 && sb[sb.Length - 1] != ' ') { sb.Append(" "); } break; } } sb.TrimStart(); if (sb.Length > 0) { block.BlockElements.Add(new ScriptText(sb.ToString())); sb.Clear(); } RemoveLastElementIfVerse(block); break; } if (block != null && block.BlockElements.Count > 0) { blocks.Add(block); } } return(blocks); }
/// ------------------------------------------------------------------------------------ /// <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 = StringUtils.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; int hvo = m_book.Cache.GetIdFromGuid(guidObj); if (hvo > 0) { switch (m_book.Cache.GetClassOfObject(hvo)) { case StFootnote.kclsidStFootnote: m_outerText = m_currentScrText; // footnotes are StTexts m_currentScrText = new TokenizableText(new StText(m_book.Cache, hvo), TextType.Note); return(MoveNext()); case CmPicture.kclsidCmPicture: { m_outerText = m_currentScrText; CmPicture pict = new CmPicture(m_book.Cache, hvo); m_currentScrText = new TokenizableText( pict.Caption.VernacularDefaultWritingSystem.UnderlyingTsString, ScrStyleNames.Figure, TextType.PictureCaption, pict, (int)CmPicture.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 == (int)ScrBook.ScrBookTags.kflidTitle) { // Get first section head text. CurrentSectionIndex = 0; } else if (m_currentScrText.m_text.OwningFlid == (int)ScrSection.ScrSectionTags.kflidHeading) { m_currentScrText = new TokenizableText(m_currentSection.ContentOA, m_currentSection.IsIntro ? TextType.Other : TextType.Verse); } else { Debug.Assert(m_currentScrText.m_text.OwningFlid == (int)ScrSection.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()); }