Ejemplo n.º 1
0
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Get the start and end reference of the specified position <paramref name="ivPos"/>
        /// in the paragraph. Section reference could be used, if available, to fill in missing
        /// information, but (at least for now) we will not search back into previous sections.
        /// </summary>
        /// <param name="wsBT">HVO of the writing system of the BT to search, or -1 to search
        /// the vernacular.</param>
        /// <param name="ivPos">Character offset in the paragraph.</param>
        /// <param name="fAssocPrev">Consider this position to be associated with any preceding
        /// text in the paragraph (in the case where ichPos is at a chapter boundary).</param>
        /// <param name="refStart">[out] Start reference</param>
        /// <param name="refEnd">[out] End reference</param>
        /// <remarks><p><paramref name="refStart"/> and <paramref name="refEnd"/> are only
        /// different if we have bridged verse numbers.</p>
        /// <p>May return incomplete or invalid reference if, for example, the section
        /// object does not have a valid start reference.</p>
        /// <p>If ivPos LT zero, we will not search this para, but look only in previous
        /// paragraphs</p></remarks>
        /// ------------------------------------------------------------------------------------
        public void GetBCVRefAtPosition(int wsBT, int ivPos, bool fAssocPrev,
                                        out BCVRef refStart, out BCVRef refEnd)
        {
            refStart = new BCVRef();
            refEnd   = new BCVRef();

            // Might be trying to get the BCVRef in a footnote
            int ownerOwnFlid = m_cache.GetOwningFlidOfObject(OwnerHVO);

            if (ownerOwnFlid == (int)ScrBook.ScrBookTags.kflidFootnotes)
            {
                ScrFootnote footnote = new ScrFootnote(m_cache, OwnerHVO);
                refStart = footnote.StartRef;
                refEnd   = footnote.StartRef;
                return;
            }

            BCVRef            refStartT = new BCVRef();
            BCVRef            refEndT   = new BCVRef();
            ChapterVerseFound found     = ChapterVerseFound.None;
            bool       fGotVerse        = false;
            ScrTxtPara para             = this; // curent paragraph being examined for reference
            int        chvoParas        = 0;    // count of paragraphs in the section
            int        ihvoPara         = 0;    // index of the paragraph within the section

            BCVRef sectRefStart;
            BCVRef sectRefEnd;

            GetSectionStartAndEndRefs(out sectRefStart, out sectRefEnd);

            while (true)
            {
                if (para == this)
                {
                    found = para.GetBCVRefAtPosWithinPara(wsBT, ivPos, fAssocPrev, out refStartT,
                                                          out refEndT);
                }
                else
                {
                    found = para.GetBCVRefAtEndOfPara(out refStartT, out refEndT);
                }

                // if we found a verse, remember it
                if (!fGotVerse && ((found & ChapterVerseFound.Verse) != 0))
                {
                    refStart.Verse = refStartT.Verse;
                    refEnd.Verse   = refEndT.Verse;
                    fGotVerse      = true;
                }

                // if we found a chapter, process it
                if ((found & ChapterVerseFound.Chapter) != 0)
                {
                    if (sectRefStart != null && !sectRefStart.IsEmpty)
                    {
                        refStart.Book = refEnd.Book = sectRefStart.Book;                         //may not exist
                    }
                    refStart.Chapter = refEnd.Chapter = refStartT.Chapter;

                    // GetBCVwithinPara always returns a verse if it finds a chapter number
                    // so we have already built the full reference
                    Debug.Assert(fGotVerse);
                    return;
                }

                // We got to the beginning of the paragraph being edited and still haven't
                // found a decent reference for our edited text, so keep looking back to
                // get it from a previous paragraph.

                // First time thru, figure out which paragraph we are in
                if (chvoParas == 0)
                {
                    // REVIEW (EberhardB): does this work if not all paragraphs are
                    // loaded in the cache?
                    chvoParas = m_cache.GetVectorSize(OwnerHVO,
                                                      (int)StText.StTextTags.kflidParagraphs);
                    // Go forward through vector of paragraphs to find the one being parsed
                    for (ihvoPara = 0; ihvoPara < chvoParas; ihvoPara++)
                    {
                        int hvoPara = m_cache.GetVectorItem(OwnerHVO,
                                                            (int)StText.StTextTags.kflidParagraphs, ihvoPara);
                        if (hvoPara == Hvo)
                        {
                            break;                             // found our current para
                        }
                    }
                }

                // Move to the previous paragraph
                ihvoPara--;

                if (ihvoPara < 0)
                {
                    // We are at the beginning of the section. We can't look back any further.
                    // ENHANCE TomB: If we search all the way through to the beginning of the
                    // section and never get a valid reference, this section begins in the
                    // middle of a verse or chapter (unlikely in the case of a verse, but
                    // quite likely in the case of a chapter). OR (most likely) this edit
                    // happened at the very beginning of the section, and when we start
                    // parsing, the first thing we'll get is a decent reference.
                    // REVIEW: we're using the section reference, but since they don't get
                    // updated, a change (like removing a chapter) in a previous section
                    // could mess up this section.
                    if (fGotVerse)
                    {
                        // Use the verse we got previously (already set), along with the
                        // first chapter for the section and the book, if available.
                        if (sectRefStart != 0)
                        {
                            refStart.Chapter = refEnd.Chapter = sectRefStart.Chapter;
                            refStart.Book    = refEnd.Book = sectRefStart.Book;
                        }
                    }
                    else
                    {
                        // REVIEW:
                        // For now, we're just using the first verse for the section, but this
                        // could be wrong if the section begins in the middle of a verse bridge
                        // or misleading if the section just doesn't yet have verse numbers
                        // marked.
                        if (sectRefStart != 0)
                        {
                            refStart = new BCVRef(sectRefStart);
                            refEnd   = new BCVRef(sectRefStart);
                        }

                        // If we are looking for a negative position in the first para of a section
                        // the needed result is not precisely defined yet,
                        // but this is where you could set it
//						if (para == this && ivPos < 0)
//							refStart.Verse = refEnd.Verse = ????;
                    }
                    return;
                }

                // Set up for the previous paragraph in this section, and we'll try again
                int hvoNewPara = m_cache.GetVectorItem(OwnerHVO,
                                                       (int)StText.StTextTags.kflidParagraphs, ihvoPara);
                // use a special constructor since we already know the section refs
                para = new ScrTxtPara(m_cache, hvoNewPara, false, false);
            }
        }
Ejemplo n.º 2
0
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Find the start and end reference, by searching backwards in the given ITsString
        /// from the given position.
        /// </summary>
        /// <param name="tss">the given ITsString</param>
        /// <param name="ichPos">Index of character in paragraph whose reference we want</param>
        /// <param name="fAssocPrev">Consider this position to be associated with any preceding
        /// text in the paragraph (in the case where ichPos is at a chapter boundary).</param>
        /// <param name="refStart">[out] Start reference for the paragraph.</param>
        /// <param name="refEnd">[out] End reference for the paragraph.</param>
        /// <returns>A value of <see cref="ChapterVerseFound"/> that tells if a chapter and/or
        /// verse number was found in this paragraph.</returns>
        /// <remarks>If ichPos LT zero, we will not search this para, and simply return.
        /// Be careful not to use this method to search the contents of paragraph using
        /// character offsets from the BT!
        /// </remarks>
        /// ------------------------------------------------------------------------------------
        static public ChapterVerseFound GetBCVRefAtPosWithinTss(ITsString tss, int ichPos,
                                                                bool fAssocPrev, out BCVRef refStart, out BCVRef refEnd)
        {
            refStart = new BCVRef();
            refEnd   = new BCVRef();
            ChapterVerseFound retVal = ChapterVerseFound.None;

            if (tss.Length <= 0)
            {
                return(retVal);
            }

            TsRunInfo    tsi;
            ITsTextProps ttpRun;
            bool         fGotVerse = false;

            int ich = ichPos;

            if (ich > tss.Length)
            {
                ich = tss.Length;
            }
            while (ich >= 0)
            {
                // Get props of current run.
                ttpRun = tss.FetchRunInfoAt(ich, out tsi);

                // If we're at (the front edge of) a C/V number boundary and the
                // caller said to associate the position with the previous material, then
                // ignore this run unless we're at the beginning of the para.
                // The run is actually the *following*  run, which we don't care about.
                if (!fAssocPrev || ichPos <= 0 || ichPos != tsi.ichMin)
                {
                    // See if it is our verse number style.
                    if (!fGotVerse && StStyle.IsStyle(ttpRun, ScrStyleNames.VerseNumber))
                    {
                        // The whole run is the verse number. Extract it.
                        string sVerseNum = tss.get_RunText(tsi.irun);
                        //					string sVerseNum = tss.Text.Substring(tsi.ichMin,
                        //						tsi.ichLim - tsi.ichMin);
                        int startVerse, endVerse;
                        ScrReference.VerseToInt(sVerseNum, out startVerse, out endVerse);
                        refStart.Verse = startVerse;
                        refEnd.Verse   = endVerse;
                        fGotVerse      = true;
                        retVal         = ChapterVerseFound.Verse;
                    }
                    // 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 = tss.get_RunText(tsi.irun);
                            int    nChapter    = ScrReference.ChapterToInt(sChapterNum);
                            refStart.Chapter = refEnd.Chapter = nChapter;

                            if (fGotVerse)
                            {
                                // Found a chapter number to go with the verse number we
                                // already found, so build the full reference using this
                                // chapter with the previously found verse (already set).
                                retVal |= ChapterVerseFound.Chapter;
                            }
                            else
                            {
                                // Found a chapter number but no verse number, so assume the
                                // edited text is in verse 1 of the chapter.
                                refStart.Verse = refEnd.Verse = 1;
                                fGotVerse      = true;
                                retVal         = ChapterVerseFound.Chapter | ChapterVerseFound.Verse;
                            }
                            break;
                        }
                        catch (ArgumentException)
                        {
                            // ignore runs with invalid Chapter numbers
                        }
                    }
                }

                // move index (going backwards) to the character just before the Min of the run
                // we just looked at
                ich = tsi.ichMin - 1;
            }
            return(retVal);
        }