예제 #1
0
        /// --------------------------------------------------------------------------------
        /// <summary>
        /// Determines whether the ending reference of the previous section and the starting
        /// reference of the following section are contiguous.
        /// </summary>
        /// <param name="endRefOfSection">The ending reference of section.</param>
        /// <param name="startRefOfNextSection">The starting reference of following section.</param>
        /// <param name="bookId">The canonical number for the current book.</param>
        /// <param name="versification">The versification.</param>
        /// <returns>
        ///     <c>true</c> if the sections do not have contiguous references, <c>false</c>
        /// otherwise
        /// </returns>
        /// --------------------------------------------------------------------------------
        private static bool RefHasGap(BCVRef endRefOfSection, BCVRef startRefOfNextSection,
                                      int bookId, ScrVers versification)
        {
            if (endRefOfSection.Chapter == startRefOfNextSection.Chapter)
            {
                // For references in the same chapter, determine whether the starting verse
                // in the next section is the same or just one more than the end of the
                // current section.
                return((endRefOfSection.Verse + 1) < startRefOfNextSection.Verse);
            }

            VersificationTable verseTable = VersificationTable.Get(versification);

            if ((endRefOfSection.Chapter + 1) == startRefOfNextSection.Chapter)
            {
                if (endRefOfSection.Verse != verseTable.LastVerse(bookId, endRefOfSection.Verse) ||
                    startRefOfNextSection.Verse == 1)
                {
                    // The current section's last verse is the end of the chapter and the
                    // next section starts with the first verse of the next chapter.
                    return(false);
                }
            }

            return(true);
        }
예제 #2
0
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Constructs and returns a new ScrReference representing Revelation 22:21 (or whatver
        /// the last verse is in Revelation for the current default versification scheme).
        /// </summary>
        /// <param name="versification">The versification scheme.</param>
        /// ------------------------------------------------------------------------------------
        public static ScrReference EndOfBible(Paratext.ScrVers versification)
        {
            VersificationTable versificationTable = VersificationTable.Get(versification);
            int lastChapter = versificationTable.LastChapter(LastBook);

            return(new ScrReference(LastBook, lastChapter,
                                    versificationTable.LastVerse(LastBook, lastChapter), versification));
        }
예제 #3
0
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Check verse numbers.
        /// </summary>
        /// ------------------------------------------------------------------------------------
        private void CheckVerseNumbers(ChapterToken chapToken, int bookId)
        {
            int  lastVrsInChap     = m_versification.LastVerse(bookId, chapToken.ChapterNumber);
            int  nextExpectedVerse = 1;
            bool expectingPartB    = false;
            int  prevVerseStart    = 0;
            int  prevVerseEnd      = 0;

            ITextToken[] versesFound = new ITextToken[lastVrsInChap + 1];
            versesFound[0] = chapToken.Token;

            foreach (VerseToken verseToken in chapToken.VerseTokens)
            {
                ITextToken token            = verseToken.VerseNumber;
                ITextToken reportedToken    = token;
                string     msg              = null;
                int        offset           = 0;
                int        length           = token.Text.Length;
                object[]   errorArgs        = null;
                bool       countFoundVerses = false;
                int        curVerseStart;
                int        curVerseEnd;
                VersePart  vrsPart;

                if (verseToken.ImplicitVerseNumber == 1)
                {
                    versesFound[1] = token;
                    continue;
                }

                ParseVerseResult parseResult = ParseVerseNumber(token.Text,
                                                                out curVerseStart, out curVerseEnd, out vrsPart);

                if (parseResult == ParseVerseResult.ValidWithSpaceInVerse)
                {
                    // Log error telling user there are spaces before or after the verse
                    // number. This means the space(s) have the verse number style. This isn't
                    // considered an invalid verse number, but we do need to tell the user.
                    AddError(token, 0, token.Text.Length,
                             Localize("Space found in verse number"), token.Text);
                }
                else if (parseResult == ParseVerseResult.ValidWithSpaceInVerseBridge)
                {
                    // Log error telling user there are spaces in a verse bridge. This
                    // means the space(s) have the verse number style. This isn't considered
                    // an invalid verse number, but we do need to tell the user.
                    AddError(token, 0, token.Text.Length,
                             Localize("Space found in verse bridge"), token.Text);
                }

                if (parseResult == ParseVerseResult.Invalid)
                {
                    msg = Localize("Invalid verse number");
                }
                else if ((parseResult != ParseVerseResult.InvalidFormat) && VersesAlreadyFound(curVerseStart, curVerseEnd, versesFound) &&
                         !(expectingPartB && vrsPart == VersePart.PartB))
                {
                    if (AnyOverlappingVerses(curVerseStart, curVerseEnd,
                                             prevVerseStart, prevVerseEnd, out errorArgs))
                    {
                        // Duplicate verse(s) found.
                        msg = (errorArgs.Length == 1 ?
                               Localize("Duplicate verse number") :
                               Localize("Duplicate verse numbers"));
                    }
                    else
                    {
                        // Verse number(s) are unexpected
                        msg = (curVerseStart == curVerseEnd ?
                               Localize("Unexpected verse number") :
                               Localize("Unexpected verse numbers"));
                    }
                }
                else if (AnyOverlappingVerses(curVerseStart, curVerseEnd,
                                              lastVrsInChap + 1, int.MaxValue, out errorArgs))
                {
                    countFoundVerses = true;
                    // Start and/or end verse is out of range
                    msg = (errorArgs.Length == 1 ?
                           Localize("Verse number out of range") :
                           Localize("Verse numbers out of range"));
                }
                else if (curVerseStart < nextExpectedVerse)
                {
                    // Verse number(s) are out of order
                    countFoundVerses = true;
                    if (nextExpectedVerse <= lastVrsInChap)
                    {
                        errorArgs = new object[] { nextExpectedVerse };
                        msg       = (curVerseStart == curVerseEnd ?
                                     Localize("Verse number out of order; expected verse {0}") :
                                     Localize("Verse numbers out of order; expected verse {0}"));
                    }
                    else
                    {
                        msg = (curVerseStart == curVerseEnd ?
                               Localize("Verse number out of order") :
                               Localize("Verse numbers out of order"));
                    }
                }
                else if (((vrsPart == VersePart.PartB) != expectingPartB) &&
                         (curVerseStart == curVerseEnd))
                {
                    // Missing part A or B
                    // TODO: cover cases like "4a 5-7" and "4 5b-7". This would require
                    // ParseVerseNumber() to detect verse parts at the beginning of bridges.
                    reportedToken = (vrsPart == VersePart.PartB ? token : versesFound[prevVerseEnd]);
                    msg           = Localize("Missing verse number {0}");
                    offset        = (vrsPart == VersePart.PartB ? 0 : reportedToken.Text.Length);
                    length        = 0;
                    int    reportedVrsNum = (vrsPart == VersePart.PartB ? curVerseStart : prevVerseEnd);
                    string fmt            = (vrsPart == VersePart.PartB ? "{0}a" : "{0}b");
                    errorArgs        = new object[] { string.Format(fmt, reportedVrsNum) };
                    countFoundVerses = true;
                }
                else if ((vrsPart == VersePart.PartB && curVerseStart > prevVerseEnd) &&
                         (curVerseStart == curVerseEnd))
                {
                    // Missing both a part B and A
                    reportedToken = versesFound[prevVerseEnd];

                    AddError(reportedToken, reportedToken.Text.Length, 0,
                             Localize("Missing verse number {0}"),
                             new object[] { string.Format("{0}b", prevVerseEnd) });

                    AddError(token, 0, 0, Localize("Missing verse number {0}"),
                             new object[] { string.Format("{0}a", curVerseStart) });
                }

                if (msg != null)
                {
                    // Report the error found.
                    if (errorArgs == null)
                    {
                        AddError(reportedToken, offset, length, msg);
                    }
                    else
                    {
                        AddError(reportedToken, offset, length, msg, errorArgs);
                    }
                }

                if (msg == null || countFoundVerses)
                {
                    // No error was found for the current verse range so set all the verses
                    // in our found verse list corresponding to those in the range.
                    for (int i = curVerseStart; i <= Math.Min(curVerseEnd, lastVrsInChap); i++)
                    {
                        versesFound[i] = token;
                    }
                }

                if (parseResult == ParseVerseResult.InvalidFormat)
                {
                    AddError(token, 0, token.Text.Length, Localize("Invalid verse number"), token.Text);
                }

                // only worry about this if the chapter and/or verse tokens are in order
                if (verseToken.VerseTextCount < 1)
                {
                    AddError(verseToken.VerseNumber, 0, verseToken.VerseNumber.Text.Length,
                             Localize("Missing verse text in verse {0}"), verseToken.VerseNumber.Text);
                }

                // Determine next expected verse.
                // Don't expect a partB if there was an error with partA
                expectingPartB = (vrsPart == VersePart.PartA && msg == null);
                if (!expectingPartB && curVerseEnd <= lastVrsInChap)
                {
                    nextExpectedVerse = curVerseEnd + 1;
                }

                prevVerseStart = curVerseStart;
                prevVerseEnd   = curVerseEnd;
            }

            CheckForMissingVerses(versesFound, bookId, chapToken.ChapterNumber);
        }